Symfony2 – Doctrine2: Cross-Database Join Column throws Mapping-Exception

Привет, хочу сделать соединение между двумя объектами. Объекты находятся в разных базах данных:

Вот как я настроил конфигурацию своей базы данных:

doctrine: dbal: default_connection: default connections: default: driver: %database_driver% host: %database_host% port: %database_port% dbname: %database_name% user: %database_user% password: %database_password% charset: UTF8 mapping_types: enum: string data_warehouse: driver: %database_data_warehouse_driver% host: %database_data_warehouse_host% port: %database_data_warehouse_port% dbname: %database_data_warehouse_name% user: %database_data_warehouse_user% password: %database_data_warehouse_password% charset: UTF8 mapping_types: enum: string orm: auto_generate_proxy_classes: %kernel.debug% default_entity_manager: default entity_managers: default: connection: default mappings: MyBundle1: ~ data_warehouse: connection: data_warehouse mappings: MyBundle2: ~ 

И это мои сущности:

 namespace My\Bundle1\Entity; use My\Bundle1\Entity\MyBundle2Entity; class MyBundle1Entity { /** * @var integer * * @ORM\Column(name="id", type="integer", nullable=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; } namespace My\Bundle2\Entity; class MyBundle2Entity { /** * @var integer * * @ORM\Column(name="id", type="integer", nullable=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var MyBundle1Entity * * @ORM\ManyToOne( targetEntity="My\Bundle1\Entity\MyBundle1Entity") * @ORM\JoinColumn(name="my_bundle1_entity_id", nullable=true) */ private $myBundle1Entity; } 

Когда я пытаюсь использовать команду doctrine: schema: update, я получаю сообщение об ошибке:

 php app/console doctrine:schema:create --dump-sql --em=data_warehouse 

Ошибка:

[Учение \ Common \ Постоянство \ Mapping \ MappingException]
Класс «My \ Bundle1 \ Entity \ Bundle1Entity» не найден в цепочках имен, заданных цепочкой My \ Bundle2 \ Entity \ Bundle2Entity

Является ли моя установка правильной или я делаю что-то совершенно неправильное? Я предполагаю, что я определяю двух менеджеров сущностей, а также соединения и рассказываю им, какие пакеты они должны обрабатывать. Я гарантирую, что в каждой группе есть только объекты из одной базы данных.

Спасибо за вашу помощь

Related of "Symfony2 – Doctrine2: Cross-Database Join Column throws Mapping-Exception"

Похоже, этот вопрос старый, но на него никогда не отвечали. Я надеюсь, что этот ответ поможет коллегам-гуглерам споткнуться по этому вопросу.

Вы не можете установить прямую связь между сущностями между менеджерами сущностей. Однако вы можете установить отношения между пакетами, если они имеют один и тот же менеджер сущностей.

Отношения между двумя объектами, использующими один и тот же менеджер сущностей [2.2+]:

Взгляните на документы Symfony по этому вопросу

По существу, в Bundle1 создайте интерфейс, а затем реализуйте его на своей сущности. В Bundle2 свяжите свою аннотацию @ManyToOne с интерфейсом, а не с самим объектом. Затем сообщите Symfony в конфиге, как разрешить интерфейс.

Bundle1:

 <?php // src/My/Bundle1/Entity/Bundle1Entity.php namespace My\Bundle1\Entity; use My\Bundle1\Entity\MyBundle2Entity; // <-- NOT NEEDED interface Bundle1EntityInterface {} class MyBundle1Entity implements Bundle1EntityInterface { // ... } 

Bundle2:

 <?php // src/My/Bundle2/Entity/Bundle2Entity.php namespace My\Bundle2\Entity; class MyBundle2Entity { // ... /** * @var MyBundle1Entity * * @ORM\ManyToOne(targetEntity="My\Bundle1\Entity\Bundle1EntityInterface") * @ORM\JoinColumn(name="my_bundle1_entity_id", nullable=true) */ private $myBundle1Entity; } 

Конфигурация приложения:

 # app/config/config.yml doctrine: # .... orm: # .... resolve_target_entities: My\Bundle1\Entity\Bundle1EntityInterface: My\Bundle1\Entity\Bundle1Entity 

Отношения между двумя объектами, использующими другой менеджер объектов

Поскольку объекты не могут быть привязаны напрямую, вы должны подключиться к событию postLoad, чтобы настроить ссылку, при сохранении идентификатора вручную. См. Документы для примера и объяснения смешивания объекта MongoDB с объектом ORM.

Вот скелет (удалены геттеры / сеттеры), используя 2 менеджера сущностей:

Объекты:

 <?php // src/My/Bundle1/Entity/Bundle1Entity.php namespace My\Bundle1\Entity; class MyBundle1Entity { /** * @var integer * * @ORM\Column(name="id", type="integer", nullable=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; } // src/My/Bundle2/Entity/Bundle2Entity.php namespace My\Bundle2\Entity; class MyBundle2Entity { /** * @var integer * * @ORM\Column(name="id", type="integer", nullable=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var integer * * @ORM\Column(type="integer") */ private $myBundle1EntityId; /** * @var MyBundle1Entity */ private $myBundle1Entity; public function setMyBundle1Entity($entity) { $this->myBundle1EntityId = $entity->getId(); $this->myBundle1Entity = $entity; } } 

Слушатель событий:

 <?php use Doctrine\ORM\EntityManager; use Doctrine\ORM\Event\LifecycleEventArgs; class MyEventSubscriber { public function __construct(EntityManager $bundle1Em) { $this->bundle1Em = $bundle1Em; } public function postLoad(LifecycleEventArgs $eventArgs) { $myBundle2Entity = $eventArgs->getEntity(); $defaultEm = $eventArgs->getEntityManager(); $myBundle2EntityReflProp = $defaultEm->getClassMetadata('Entity\MyBundle2Entity') ->reflClass->getProperty('myBundle1Entity'); $myBundle2EntityReflProp->setAccessible(true); $myBundle2EntityReflProp->setValue( $myBundle1Entity, $this->bundle1Em->getReference('Entity\MyBundle1Entity', $myBundle2Entity->getMyBundle1Id()) ); } } 

Очевидно, вам нужно будет зарегистрировать прослушиватель событий и передать диспетчер сущностей пакета 1 в качестве аргумента.