Symfony2/Doctrine2:在侦听器中管理多个实体管理器的问题


Symfony2/Doctrine2: Issues managing multiple entity manager inside a listener

http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/cookbook/blending-orm-and-mongodb-odm.html#event-subscriber遵循该配方,当我到达事件订阅者时,我无法注入正确的entity manager,即在构造函数中初始化$this->dm的那个。

据我了解,正在加载的实体使用的实体管理器可以通过$em = $eventArgs->getEntityManager();检索,然后我需要另一个我通过以下方式inject的实体管理器:

   服务业:        postload.listener:        class: myVendor''myFooBarBundle''Listener''myEntityListener        标签:            - { 名称:doctrine.event_listener,事件:后加载 }        参数:            - "@doctrine.orm.foobar_entity_manager">

这些是我的实体经理:

orm.yml        或:        entity_managers:            违约:                连接:默认                映射:                    myVendormyFooBarBundle:                        前缀:"myVendor''myFooBarBundle''Entity"                        类型:注释                        is_bundle:真                        目录:"实体"            福巴:                连接: 福巴                映射:                    myVendormyFooBarBundle:                        前缀:"myVendor''myFooBarBundle''View"                        类型:注释                        is_bundle:真                        目录:"查看">

使用上述策略injecting foobar entity manager时,出现以下错误:

Circular reference detected for service "postload.listener", path: "routing.loader -> routing.db.loader -> doctrine.orm.default_entity_manager -> doctrine.dbal.default_connection -> postload.listener -> doctrine.orm.fooba_entity_manager -> doctrine.dbal.foobar_connection".  

这就是myVendor'myFooBarBundle'Listener'myEntityListener类:

    class myFooBarEntityListener    {        public function __construct( ''Doctrine''ORM''EntityManager $em (        {            $this->em = $em;        }        public function postLoad( Lifecycle EventArgs $eventArgs (        {            $myEntity = $eventArgs->getEntity((;            if( $myEntity instanceof ''myVendor''myFooBarBundle''Entity''myEntity (            {                $em = $eventArgs->getEntityManager((;                $fooBarReflProp = $em->getClassMetadata( 'myVendor''myFooBarBundle''Entity''Entity''myEntity' (->reflClass->getProperty( 'FooBarEntity' (;                $fooBarReflProp->setAccess( true (;                $fooBarEntity = $this->em->getRepository( 'myVendor''myFooBarBundle''View''myFooBarEntity' (->findOneBy( array( 'id' => $myEntity->getFooBarEntityId(( ( (;                $fooBarReflProp->setValue( $myEntity, $fooBarEntity (;            }        }    }

另外为了避免我尝试not注入foobar entity manager并通过LifecycleEventArgs $eventArgs circular reference error

    class myFooBarEntityListener    {        public function postLoad( Lifecycle EventArgs $eventArgs (        {            $myEntity = $eventArgs->getEntity((;            if( $myEntity instanceof ''myVendor''myFooBarBundle''Entity''myEntity (            {                $em = $eventArgs->getEntityManager((;                $fooBarReflProp = $em->getClassMetadata( 'myVendor''myFooBarBundle''Entity''Entity''myEntity' (->reflClass->getProperty( 'FooBarEntity' (;                $fooBarReflProp->setAccess( true (;                请注意,在这里我应该如何通过$eventArgs获得正确的实体管理器                $fooBarEntity = $eventArgs->getEntityManager('foobar'(->getRepository( 'myVendor''myFooBarBundle''View''myFooBarEntity' (->findOneBy( array( 'id' => $myEntity->getFooBarEntityId(( (;                $fooBarReflProp->setValue( $myEntity, $fooBarEntity (;            }        }    }

最后一个实现通过我出现以下错误:

An exception has been thrown during the rendering of a template ("Class myVendor'myFooBarBundle'View'myFooBarEntity is not a valid entity or mapped super class.") in "SonataAdminBundle:CRUD:base_list.html.twig" at line 28.

上述错误是由$fooBarEntity = $eventArgs->getEntityManager('foobar')->getRepository( 'myVendor'myFooBarBundle'View'myFooBarEntity' )->findOneBy( array( 'id' => $myEntity->getFooBarEntityId() ) );引起的,因为当我放置回显'hello';d ie((时,错误不会抛出,但是当放置在该行之后时,错误被抛出并且hello没有显示。这个错误让我觉得虽然我明确地通过$eventArgs->getEntityManager('foobar')获得了foobar连接,但它仍然给了我default connection/entity manager

为了仔细检查myVendor'myFooBarBundle'View'myFooBarEntity语法,我转到octrine'ORM'Mapping'Driver'DriverChain并放置了以下代码:

    if( strpos( $className, 'myFooBarEntity' ( (    {        回声"类:".$className。''";        foreach ($this->_drivers as $namespace => $driver(        {            回显"命名空间:".$namespace"。'";            $bool = strpos($className, $namespace(;            var_dump($bool(;            回显"''";        }    }    死((;

该DriverChain代码给了我以下内容,这就是为什么我认为从未使用过"foobar"连接,或者symfony在定义实体管理器和要使用的命名空间orm.yml文件中具有某种错误解释。

class: myVendor''myFooBarBundle''View''myFooBarEntity

命名空间:myVendor''myFooBarBundle''Entity布尔值(假(

如果我在myVendor'myFooBarBundle'View'myFooBarEntity里面查看entity词,我只会找到实体定义@ORM'Entity,也@ORM'OneToMany( targetEntity=.....)与另一个实体的关系。

我希望有人能帮忙,因为这让我发疯。多谢!!

我找到了一个解决方案:

services:
    postload.listener:
    class: myVendor'myFooBarBundle'Listener'myEntityListener
    tags:
        - { name: doctrine.event_listener, event: postLoad }
    arguments:
        - @doctrine

我的听众:

namespace myVendor'myFooBarBundle'Listener'myEntityListener;
use Symfony'Bundle'DoctrineBundle'Registry;
class myFooBarEntityListener
{
    private $reg;
    public function __construct(Registry $reg)
    {
        //dont't put your entitymanager otherwise a loop appear during creation
        $this->reg = $reg;
    }
    public function postLoad( LifecycleEventArgs $eventArgs )
    {
        $myEntity = $eventArgs->getEntity();
        if( $myEntity instanceof 'myVendor'myFooBarBundle'Entity'myEntity )
        {
            $em = $this->reg->getEntityManager('not_default');
            $userPointdbManager = $em->getRepository('FullerUserBundle:UserPointdb');
            ....
        }
    }
}

您现在可以使用多个实体管理器。

我想我看到了你的问题:

正在尝试处理不由您正在使用的实体管理器管理的对象。

原因是在您的第一个示例中,您在服务doctrine.orm.foobar_entity_manager上工作,不知道myVendor'myFooBarBundle'Entity

在第二个中,您尝试使用以下方法访问不同的实体管理器: $eventArgs->getEntityManager('foobar')但这不起作用。EventArgs只附加到一个实体管理器,并且没有参数(如"foobar"(可以访问另一个实体管理器。

所以我在这里看到的最佳解决方案是像你的第一个想法一样行事,但注入两个实体经理:

services:
    postload.listener:
    class: myVendor'myFooBarBundle'Listener'myEntityListener
    tags:
        - { name: doctrine.event_listener, event: postLoad }
    arguments:
        - "@doctrine.orm.default_entity_manager"
        - "@doctrine.orm.foobar_entity_manager"

如果您有循环依赖关系检测,请尝试注入 doctrine 服务,它是 Symfony'Bridge'Doctrine'ManagerRegistry 的实例。

不要将 Registry 设置为参数,而是将 RegistryInterface 设置为参数(使用 Symfony''Bridge''Doctrine''RegistryInterface(

更改后,最后一个示例开始为我工作使用 Symfony''Bundle''DoctrineBundle''Registry;使用 Doctrine''Bundle''DoctrineBundle''Registry;。

所以它应该是:

namespace myVendor''myFooBarBundle''Listener''myEntityListener;使用原则''捆绑包''原则捆绑包''注册表class myFooBarEntityListener{    私人$reg;    公共功能__construct(注册表$reg(    {        不要放置实体管理器,否则在创建过程中会出现循环        $this->reg = $reg;    }    public function postLoad( Lifecycle EventArgs $eventArgs (    {        $myEntity = $eventArgs->getEntity((;        if( $myEntity instanceof ''myVendor''myFooBarBundle''Entity''myEntity (        {            $em = $this->reg->getEntityManager('not_default'(;            $userPointdbManager = $em->getRepository('FullerUserBundle:UserPointdb'(;            ....        }    }}