2012-03-02 43 views
2

內的多個實體管理器的問題我正在追蹤那幾招http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/cookbook/blending-orm-and-mongodb-odm.html#event-subscriber,當我到達事件訂閱我不能注射合適的entity manager,一個名爲$this->dm在構造函數初始化。的Symfony2/Doctrine2:管理聽衆

據我所知,通過該被加載可通過$em = $eventArgs->getEntityManager();被檢索的實體所使用的實體管理器然後我需要另一個我以下列方式inject

 
    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" 
使用上述策略,我得到以下錯誤

injecting

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(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); 
      } 
     } 
    } 

也避免了circular reference error我已經試過not注入foobar entity manager並通過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); 
      } 
     } 
    } 

這最後落實得來我下面錯誤:

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()));造成的,因爲當我放置echo'hello'; die();就在該行之前,錯誤不會被拋出,但是當放在行後錯誤被拋出時,hello不會顯示。該錯誤使我認爲,雖然我明確通過$eventArgs->getEntityManager('foobar')得到foobar連接,但它仍然給我defaultconnection/entity manager

爲了仔細檢查myVendor\myFooBarBundle\View\myFooBarEntity語法我去octrine\ORM\Mapping\Driver\DriverChain,放在下面的代碼:

 
    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文件,它定義了實體管理器以及要使用的命名空間。

類:的Myvendor \ myFooBarBundle \查看\ myFooBarEntity

命名空間:的Myvendor \ myFooBarBundle \實體 布爾(假)

如果我看上去福爾內myVendor\myFooBarBundle\View\myFooBarEntityentity字我只是覺得@ORM\Entity爲實體定義和@ORM\OneToMany(targetEntity=.....)與另一個實體的關係。

我希望有人能幫忙,因爲這讓我發瘋。非常感謝!!

回答

1

我想我看到您的問題:

你試圖對不是由您正在使用的EntityManager管理的工作的entites。

原因是,在你的第一個例子中,你ony工作在服務doctrine.orm.foobar_entity_manager,這是不知道myVendor\myFooBarBundle\Entity entites。

在第二個嘗試訪問不同的entitymanager使用:$eventArgs->getEntityManager('foobar')但這不會工作。 EventArgs僅附加到一個entityManager,並且沒有參數(如'foobar')來訪問另一個。

所以最好的解決方案,我在這裏看到的是像你的第一個想法,但注射兩種entityMangers:

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

+0

感謝很多答案。我已經嘗試了這一切,注入兩個實體經理,注入服務容器,然後獲得教義服務,注入教義服務,然後獲得兩個實體經理,但我總是得到循環引用錯誤。你知道我還能做什麼?感謝高級:) – user846226 2012-03-05 10:24:58

+0

最後,我看了一下'l3pp4rd DoctrineBehaviours',並根據他的結構創建了一個更高級的偵聽器,並且從'doctrine'服務獲取這兩個連接都沒有問題。 – user846226 2012-03-05 11:35:36

+0

因此,這些答案中的任何一個都可以被標記爲已接受,或者至少可以發佈您的解決方案@ user846226?提前致謝。 – webDEVILopers 2014-09-10 07:47:16

2

我找到了一個解決方案:

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

      .... 
     } 
    } 
} 

現在,您可以使用多個實體管理器。

0

最後一個例子在更改 後使用Symfony \ Bundle \ DoctrineBundle \ Registry;使用Doctrine \ Bundle \ DoctrineBundle \ Registry ;.

所以它應該是:

 
namespace myVendor\myFooBarBundle\Listener\myEntityListener; 

use Doctrine\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'); 

      .... 
     } 
    } 
} 
0

不要設置註冊表的參數,但RegistryInterface(使用的Symfony \橋\原則\ RegistryInterface)