Я следую этому рецепту http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/cookbook/blending-orm-and-mongodb-odm.html#event-subscriber
и когда i получить доступ к подписчику события, я не могу ввести надлежащего entity manager
, тот, который назван $this->dm
инициализированным в конструкторе.
Как я понимаю, менеджер $em = $eventArgs->getEntityManager();
используемый загружаемой сущностью, может быть извлечен через $em = $eventArgs->getEntityManager();
то мне нужен другой, который я inject
следующим образом:
Сервисы: postload.listener: class: myVendor \ myFooBarBundle \ Listener \ myEntityListener теги: - {name: doctrine.event_listener, event: postLoad} аргументы: - "@ doctrine.orm.foobar_entity_manager"
Это мои руководители:
//orm.yml ORM: entity_managers: по умолчанию: соединение: по умолчанию отображения: myVendormyFooBarBundle: prefix: "myVendor \ myFooBarBundle \ Entity" Тип: аннотация is_bundle: true dir: "Entity" Foobar: соединение: foobar отображения: myVendormyFooBarBundle: prefix: "myVendor \ myFooBarBundle \ View" Тип: аннотация is_bundle: true dir: "View"
При 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; } публичная функция 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 (массив ('id' => $ myEntity-> getFooBarEntityId ())); $ fooBarReflProp-> setValue ($ myEntity, $ fooBarEntity); } } }
Также, чтобы избежать circular reference error
я попытался not
вводить foobar entity manager
LifecycleEventArgs $eventArgs
foobar entity manager
и получить его через LifecycleEventArgs $eventArgs
:
class myFooBarEntityListener { публичная функция 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); // УВЕДОМЛЕНИЕ КАК ЗДЕСЬ Я ДОЛЖЕН ПОЛУЧИТЬ МЕНЕДЖЕР ПОЛЬЗОВАТЕЛЯ ЧЕРЕЗ $ eventArgs $ fooBarEntity = $ eventArgs-> getEntityManager ('foobar') -> getRepository ('myVendor \ myFooBarBundle \ View \ myFooBarEntity') -> findOneBy (массив ('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
не отображается. Ошибка заставляет меня думать, что, хотя я явно получаю соединение foobar
через $eventArgs->getEntityManager('foobar')
он все равно дает мне connection/entity manager
по default
.
Чтобы дважды проверить myVendor\myFooBarBundle\View\myFooBarEntity
синтаксис, я пошел в octrine\ORM\Mapping\Driver\DriverChain
и разместил следующий код:
if (strpos ($ className, 'myFooBarEntity')) { echo 'Class:'. $ className. "\ n \ n"; foreach ($ this -> _ drivers как $ namespace => $ driver) { echo 'namespace:'. $ namespace. "\ n"; $ bool = strpos ($ className, $ namespace); var_dump ($ BOOL); echo "\ n \ n"; } } умереть();
Этот код DriverChain дает мне следующее, поэтому я думаю, что соединение «foobar» никогда не используется, или у symfony есть какой-то интерпретатор ошибок, orm.yml
файл orm.yml
который определяет менеджеров сущностей плюс пространства имен для использования.
class: myVendor \ myFooBarBundle \ View \ myFooBarEntity
namespace: myVendor \ myFooBarBundle \ Entity bool (false)
Если я смотрю foor, слово entity
внутри myVendor\myFooBarBundle\View\myFooBarEntity
я просто нахожу @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'); .... } } }
Теперь вы можете использовать несколько менеджеров сущностей.
Я думаю, что вижу вашу проблему:
Вы пытаетесь работать с Entites, которые не управляются с помощью entityManager, с которым вы работаете.
Причина в том, что в первом примере вы работаете над сервисом doctrine.orm.foobar_entity_manager
, который не знает о myVendor\myFooBarBundle\Entity
.
Во втором вы пытаетесь получить доступ к другим сущностным менеджерам, используя: $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
.
Последний пример начал работать для меня после изменения использования Symfony \ Bundle \ DoctrineBundle \ Registry; использовать Doctrine \ Bundle \ DoctrineBundle \ Registry ;.
Так должно быть:
namespace myVendor \ myFooBarBundle \ Listener \ myEntityListener; использование Doctrine \ Bundle \ DoctrineBundle \ Registry class myFooBarEntityListener { private $ reg; public function __construct (Registry $ reg) { // не помещаем ваш entitymanager иначе цикл появляется во время создания $ this-> reg = $ reg; } публичная функция postLoad (LifecycleEventArgs $ eventArgs) { $ myEntity = $ eventArgs-> getEntity (); if ($ myEntity instanceof \ myVendor \ myFooBarBundle \ Entity \ myEntity) { $ em = $ this-> reg-> getEntityManager ('not_default'); $ userPointdbManager = $ em-> getRepository ('FullerUserBundle: UserPointdb'); .... } } }
Не устанавливайте параметр реестра как параметр, но RegistryInterface (используйте Symfony \ Bridge \ Doctrine \ RegistryInterface)