本文介绍了Symfony2 / Doctrine2:在监听器中管理多个实体管理器的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在追踪该食谱 http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/cookbook/blending-orm-and-mongodb-odm .html#event-subscriber ,当我到达事件订阅者时,我无法注入适当的实体管理器,名为 $ this-> dm 在构造函数中初始化。

i'm following that recipe http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/cookbook/blending-orm-and-mongodb-odm.html#event-subscriber and when i get to the event subscriber i'm not able to inject the proper entity manager, the one named $this->dm initialized in the constructor.

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

As i understand, the entity manager used by the entity which is being loaded can be retrieved through $em = $eventArgs->getEntityManager(); then i need another one which i inject in the following manner:


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

这些是我的实体经理:


//orm.yml
        orm:
        entity_managers:
            default:
                connection: default
                mappings:
                    myVendormyFooBarBundle:
                        prefix: "myVendor\myFooBarBundle\Entity"
                        type: annotation
                        is_bundle: true
                        dir: "Entity"
            foobar:
                connection: foobar
                mappings:
                    myVendormyFooBarBundle:
                        prefix: "myVendor\myFooBarBundle\View"
                        type: annotation
                        is_bundle: true
                        dir: "View"

当使用上述策略注入 foobar实体管理器时,我会收到以下错误:

When injecting the foobar entity manager using the above strategy i get the following error:

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:


    class myFooBarEntityListener
    {

        public function __construct( \Doctrine\ORM\EntityManager $em )
        {
            $this->em = $em;
        }

        public function postLoad( LifecycleEventArgs $eventArgs )
        {
            $myEntity = $eventArgs->getEntity();

            if( $myEntity instanceof \myVendor\myFooBarBundle\Entity\myEntity )
            {
                $em = $eventArgs->getEntityManager();
                $fooBarReflProp = $em->getClassMetadata( 'myVendor\myFooBarBundle\Entity\myEntity' )->reflClass->getProperty( 'FooBarEntity' );
                $fooBarReflProp->setAccessible( true );
                $fooBarEntity = $this->em->getRepository( 'myVendor\myFooBarBundle\View\myFooBarEntity' )->findOneBy( array( 'id' => $myEntity->getFooBarEntityId() ) );
                $fooBarReflProp->setValue( $myEntity, $fooBarEntity );
            }
        }
    }

还要避免循环引用错误我尝试注入 foobar实体管理器,并通过 LifecycleEventArgs $ eventArgs

Also to avoid the circular reference error i've tried not to inject the foobar entity manager and get it through LifecycleEventArgs $eventArgs:


    class myFooBarEntityListener
    {

        public function postLoad( LifecycleEventArgs $eventArgs )
        {
            $myEntity = $eventArgs->getEntity();

            if( $myEntity instanceof \myVendor\myFooBarBundle\Entity\myEntity )
            {
                $em = $eventArgs->getEntityManager();
                $fooBarReflProp = $em->getClassMetadata( 'myVendor\myFooBarBundle\Entity\myEntity' )->reflClass->getProperty( 'FooBarEntity' );
                $fooBarReflProp->setAccessible( true );
                //NOTICE HOW HERE I SHOULD GET THE PROPER ENTITY MANAGER THROUGH $eventArgs
                $fooBarEntity = $eventArgs->getEntityManager('foobar')->getRepository( 'myVendor\myFooBarBundle\View\myFooBarEntity' )->findOneBy( array( 'id' => $myEntity->getFooBarEntityId() ) );
                $fooBarReflProp->setValue( $myEntity, $fooBarEntity );
            }
        }
    }

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

That last implementation throughs me the following error:

在渲染模板期间抛出异常(Class myVendor\myFooBarBundle\View\myFooBarEntity不是有效的实体或映射的超级类。)在第28行的SonataAdminBundle:CRUD:base_list.html.twig中。

上述错误是由通过 $ fooBarEntity = $ eventArgs-> getEntityManager('foobar') - > getRepository('myVendor\myFooBarBundle\View\myFooBarEntity') - > findOneBy(array('id'=因为我放置echo'hello'; die();在该行之前,错误不会被抛出,但是当放置在行之后,错误被抛出,并且 hello 未显示。这个错误让我觉得,虽然我明确地通过 $ eventArgs-> getEntityManager('foobar') foobar $ c>它仍然给我默认值 连接/实体管理器

The above error is caused by $fooBarEntity = $eventArgs->getEntityManager('foobar')->getRepository( 'myVendor\myFooBarBundle\View\myFooBarEntity' )->findOneBy( array( 'id' => $myEntity->getFooBarEntityId() ) ); because when i place echo 'hello';die(); just before that line the error is not thrown but when placed just after the line the error is thrown and hello is not shown. The error makes me think that although i'm explicitly getting the foobar connection through $eventArgs->getEntityManager('foobar') it is still giving me the default connection/entity manager.

为了双重检查 myVendor\myFooBarBundle\View\myFooBarEntity 语法我去了 octrine\ORM\ Mapping\Driver\DriverChain 并放置以下代码:

In order to double check myVendor\myFooBarBundle\View\myFooBarEntity syntax i went to octrine\ORM\Mapping\Driver\DriverChain and placed the following code:


    if( strpos( $className, 'myFooBarEntity' ) )
    {
        echo 'Class: '.$className."\n\n";
        foreach ($this->_drivers as $namespace => $driver)
        {
            echo 'namespace: '.$namespace."\n";
            $bool = strpos($className, $namespace);
            var_dump($bool);
            echo "\n\n";
        }
    }
    die();

DriverChain代码给了我以下,这就是为什么我认为'foobar'连接从未使用或symfony有某种错误解释 orm.yml 文件,定义实体管理器加上使用的命名空间。

That DriverChain code gives me the following, that's why i think 'foobar' connection is never used or symfony has some kind of bug interpreting orm.yml file which defines the entity managers plus namespaces to use.


class:myVendor\ myFooBarBundle\View\myFooBarEntity

class: myVendor\myFooBarBundle\View\myFooBarEntity

命名空间:myVendor\myFooBarBundle\Entity
bool(false)

namespace: myVendor\myFooBarBundle\Entitybool(false)

如果我在 myVendor\myFooBarBundle\View\myFooBarEntity 实体 c>我只是为实体定义找到 @ ORM\Entity ,而且 @ ORM\OneToMany(targetEntity = .....)与另一个实体的关系。

If i look foor the entity word inside myVendor\myFooBarBundle\View\myFooBarEntity i just find @ORM\Entity for the entity definition and also @ORM\OneToMany( targetEntity=.....) for the relation with another entity.

我希望有人可以帮助,因为它让我疯狂。非常感谢!

I hope someone can help, as it's driving me crazy. Thanks a lot!!

推荐答案

我找到了一个解决方案:

I found a solution:

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');

            ....
        }
    }
}

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

You can use several entity managers now.

这篇关于Symfony2 / Doctrine2:在监听器中管理多个实体管理器的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 10:15