Symfony 在实体内获取entityManager

Symfony 在实体内获取entityManager,symfony,doctrine,Symfony,Doctrine,我想用,比如: $em = $this->getEntityManager(); 在实体内部 我知道我应该将此作为一项服务来执行,但出于某些测试目的,我希望从实体访问它 有可能做到这一点吗 我试图: $em = $this->getEntityManager(); $profile_avatar = $em->getRepository('bundle:Perfils')->findOneByUser($this-getId()); 但它不起作用 致命错误:调用未定义

我想用,比如:

$em = $this->getEntityManager();
在实体内部

我知道我应该将此作为一项服务来执行,但出于某些测试目的,我希望从实体访问它

有可能做到这一点吗

我试图:

$em = $this->getEntityManager();
$profile_avatar = $em->getRepository('bundle:Perfils')->findOneByUser($this-getId());
但它不起作用

致命错误:调用未定义的方法 代理\webBundleEntityUserProxy::getEntityManager()中的 /opt/lampp/htdocs/web/src/Pct/bundle/Entity/User.php联机 449

为什么我要这样做


我有3种用户:Facebook、Twitter和MyOwnWebsite用户。他们每个人都有不同的头像链接facebook的个人资料,twitter的或其他,如果其网站用户,我从数据库中的URL检索头像。现在,我不想创建服务,因为我只是想让它工作,测试它,而不是创建最终部署。这就是为什么我试图从实体中调用实体管理器。我现在不想修改配置文件,只想修改这个实体。

从实体内部调用实体管理器是一种糟糕的做法!您应该使实体尽可能简单

您需要从实体中调用实体管理器的目的是什么?

正如评论员(再次)指出的,实体中的实体管理器是一种代码气味。对于OP希望以最少的麻烦获得实体管理器的特定情况,简单的setter注入将是最可靠的(与我最初的通过构造函数注入的示例相反)

对于在这里寻找同一问题的更好解决方案的任何其他人,有两种方法可以实现这一点:

  • 按照

  • 或者,使用
    @postLoad
    /
    @postPersist
    生命周期回调,并按照

  • 原始答案 在
    实体
    中使用
    实体管理器
    是非常糟糕的做法。这样做违背了将查询和持久化操作与实体本身分离的目的

    但是,如果您真的、真的、真的需要实体中的一个实体管理器,并且无法执行其他操作,则将其注入实体中

    class Entity
    {
        private $em;
    
        public function __contruct($em)
        {
            $this->em = $em;
        }
    }
    

    然后作为新实体($em)调用

    最好的方法是使用生命周期:
    @ORM\HasLifecycleCallbacks

    您可以根据需要使用适当的事件来获得结果:

    @postLoad
    @postPersist
    ...
    

    您需要将services.yml设置为:

    services:
        your_service_name:
            class: AppBundle\Controller\ServiceController
            arguments: [ @doctrine.orm.entity_manager ]
    
    您还需要使用以下构造函数设置控制器:

    public function __construct(\Doctrine\ORM\EntityManager $em)
    {
        $this->em = $em;
    }
    
    并在控制器中使用
    $this->em

    (例如
    $connection=$this->em->getConnection();

    我认为您应该做的是为您的实体创建自定义存储库,而不是在实体内部使用实体管理器

    在实体ORM文件中,添加如下条目(如果不使用YML,则在实体类注释中添加):

    现在,创建一个具有上述名称空间的新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;
        }
    }
    
    //您的ProfilsRepository.php
    
    我有3种用户:Facebook、Twitter和MyOwnWebsite用户。他们每个人都有不同的头像链接facebook的个人资料,twitter的或其他,如果其网站用户,我从数据库中的URL检索头像。现在,我不想创建服务,因为我只是想让它工作,测试它,而不是创建最终部署。这就是为什么我试图从实体中调用实体管理器。我现在不想修改配置文件,只想修改这个实体。@SergiCastellsaguéMillán请在您的原始帖子的评论中包含这些信息。@SergiCastellsaguéMillán可能重复!所以,最好是通过服务作为最终的、干净的解决方案来实现。是的,但你忘了说这是一个非常糟糕的解决方案PRACTICE@DonCallisto哈哈,是的,你是对的。让我结束我的回答。我只是想回答如何“在实体中获取entityManager”。我有点傻,因为我一直没有说出我的想法。如果这是如此糟糕,那么一定有一种方法我不知道如何检索相关对象,就像在任何条令关系中一样,但不知怎么过滤。我的意思是:
    $customer->getArchivedInvoices()
    而不是
    $customer->getInvoices()
    然后过滤它们。即使这是一种不好的做法,这种解决方案也更糟糕。它不是自动的,不确保实体管理器与实体相关(实体由管理器管理)。你可以在那里注射任何东西。在存储库中水合之后,实体将不会有实体管理器,因为条令不使用构造函数。真正的解决方案是使用生命周期回调(@onalbi的答案)或ObjectManagerWare接口,如下所示:嘿@Wirone,同意你的观点。谢谢你指出这一点——构造注入确实是毫无意义的。我被自己的回答逗乐了。然而(让我加上前缀)afaik,不幸的是,在实体中获得实体管理器的唯一解决方案就是注入。构造函数注入显然是不实际的,正如您所指出的,让setter注入成为更好的选择。问题是如何让实体管理器位于实体内部,而不是服务内部。
    public function __construct(\Doctrine\ORM\EntityManager $em)
    {
        $this->em = $em;
    }
    
    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
    
    //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);
             ...
    
          }
       }