我想用,比如:
$em = $this->getEntityManager();
在实体内部。
我知道我应该将其作为服务,但出于某些测试目的,我想从实体访问它。
有可能实现吗?
我试过:
$em = $this->getEntityManager();
$profile_avatar = $em->getRepository('bundle:Perfils')->findOneByUser($this-getId());
但是没有用。
致命错误:调用未定义的方法 Proxies \ webBundleEntityUserProxy :: getEntityManager()in /opt/lampp/htdocs/web/src/Pct/bundle/Entity/User.php 在线 449
为什么我要这样做?
我有3种用户:Facebook,Twitter和MyOwnWebsite用户。他们每个都有不同的头像链接Facebook的个人资料,推特或其他,如果它的myownwebsite用户,我从数据库中的URL检索头像。目前,我不想创建服务,因为我只是想让它工作,测试它,而不是创建一个最终部署。所以这就是我试图从实体中调用实体管理器的原因。到目前为止,我不想修改配置文件,只需修改此实体。
答案 0 :(得分:22)
正如评论者(再次)指出的那样,实体内部的实体经理是代码气味。对于OP的特定情况,他希望以最少的麻烦获得实体经理,简单的setter注入将是最可靠的(与我通过构造函数注入的原始示例相反)。
对于那些在此寻找同一问题的优秀解决方案的人来说,有两种方法可以达到这个目的:
按照https://stackoverflow.com/a/24766285/1349295
的建议实施ObjectManagerAware
界面
use Doctrine\Common\Persistence\ObjectManagerAware;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class Entity implements ObjectManagerAware
{
public function injectObjectManager(
ObjectManager $objectManager,
ClassMetadata $classMetadata
) {
$this->em = $objectManager;
}
}
或者,使用@postLoad
/ @postPersist
生命周期回调并使用https://stackoverflow.com/a/23793897/1349295建议的LifecycleEventArgs
参数获取实体管理器
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\HasLifecycleCallbacks()
*/
class Entity
{
/**
* @ORM\PostLoad
* @ORM\PostPersist
*/
public function fetchEntityManager(LifecycleEventArgs $args)
{
$this->setEntityManager($args->getEntityManager());
}
}
在EntityManager
内使用Entity
是非常糟糕的做法。这样做会破坏将查询和持久操作与实体本身分离的目的。
但是,如果你真的,真的,真的需要一个实体中的实体经理而不能做其他事情,那么就把它注入实体。
class Entity
{
private $em;
public function __contruct($em)
{
$this->em = $em;
}
}
然后调用new Entity($em)
。
答案 1 :(得分:5)
最好的方法是使用生命周期:@ORM\HasLifecycleCallbacks
您可以根据需要使用相应的事件:
@postLoad
@postPersist
...
答案 2 :(得分:3)
从实体内部调用实体管理器是一种不好的做法!你应该让你的实体尽可能简单。
您出于什么目的需要从实体调用实体管理器?
答案 3 :(得分:2)
我认为您应该做的是,而不是在您的实体中使用实体管理器,而是为您的实体创建自定义存储库。
在您的实体ORM文件中,按如下方式添加条目(如果不使用YML,则添加到实体类注释中):
App\Bundle\Profils:
# Replace the above as appropiate
type: entity
table: (your table)
....
repositoryClass: App\Bundle\CustomRepos\ProfilsRepository
# Replace the above as appropiate.
# I always put my custom repos in a common folder,
# such as CustomRepos
现在,创建一个具有以上命名空间的新PHP类:
//Your ProfilsRepository.php
<?php
namespace App\Bundle\CustomRepos;
use Doctrine\ORM\EntityRepository;
class ProfilsRepository extends EntityRepository
{
/**
* Will return the user url avatar given the user ID
* @param integer $userID The user id.
@return string The avatar url
*/
public function getUserProfile($userId)
{
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder();
$qb->select... (your logic to retrieve the profil object);
$query = $qb->getQuery();
$result = $query->getResult();
return $result;
}
}
最后,在您的控制器中:
// Your controller
<?php
namespace <class namespace>;
...
use App\Bundle\CustomRepos\ProfilsRepository;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
...
class YourClassNameController extends Controller
{
public function yourAction()
{
$userId = <get the user ID>;
// Pass the name of your entity manager to the
// getManager function if you have more than one and
// didn't define any default
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('Profils');
$avatar = $repo->getUserProfile($userId);
...
}
}
答案 4 :(得分:0)
您需要将services.yml设置为:
services:
your_service_name:
class: AppBundle\Controller\ServiceController
arguments: [ @doctrine.orm.entity_manager ]
您还需要使用以下构造函数设置Controller:
public function __construct(\Doctrine\ORM\EntityManager $em)
{
$this->em = $em;
}
并在控制器中使用$this->em
(例如$connection = $this->em->getConnection();
)