ReflectionException возникает при сопоставлении сущностей в Doctrine из разных баз данных.

Я пытаюсь использовать Doctrine 2 в приложении ZF2, которое содержит два модуля, каждый со своей собственной базой данных. Мне нужно использовать соединения между базами данных, чтобы я мог связать сущности из одного модуля с сущностями в другом. Вот схема UML установки.

Я пытался использовать это в своем первом объекте (я удалил ненужные параметры и операторы use):

namespace Client\Entity;

/**
 * A website.
 *
 * @ORM\Entity
 * @ORM\Table(name="users.website")
 * ...
 * @property $server
 */
class Website extends BaseEntity {

    // Other class vars ... 

    /**
     * @ORM\ManyToOne(targetEntity="Server\Entity\Server", inversedBy="websites")
     * @ORM\JoinColumn(name="server_id", referencedColumnName="id")
     */
    protected $server;

И это в моем объекте сервера:

namespace Server\Entity;

/**
 * A server.
 *
 * @ORM\Entity
 * @ORM\Table(name="servers.server")
 * ...
 * @property $websites
 */
class Server extends BaseEntity {

   // Other class vars ... 

   /**
    * @ORM\OneToMany(targetEntity="Client\Entity\Website", mappedBy="server")
    */
   protected $websites;

Это сопоставление отлично работает, когда я создаю новый объект веб-сайта (через веб-форму, которая использует DoctrineModule\Form\Element\ObjectSelect для ассоциации с сервером), но когда я перехожу к редактированию существующего веб-сайта, возникает это исключение ReflectionException:

Класс Server\Entity\Website не существует

Полную трассировку стека можно найти здесь. По какой-то причине, когда к объекту Сервер обращаются из его ассоциации с объектом Веб-сайта, он думает, что все объекты существуют в пространстве имен Server\Entity, а не Client\Entity. Что мне нужно сделать, чтобы убедиться, что сущность сервера находится в правильном пространстве имен модулей?

Команда CLI orm:info производит:

Found 7 mapped entities:
[OK]   Server\Entity\Server
[OK]   Client\Entity\Role
[OK]   Client\Entity\Website
[OK]   Client\Entity\User
[OK]   Client\Entity\Client
[OK]   Client\Entity\Permission
[OK]   Message\Entity\Notification

Но orm:validate-schema приводит к:

[Mapping]  OK - The mapping files are correct.
[Database] FAIL - The database schema is not in sync with the current mapping file.

У меня есть это в каждом из моих модулей module.config.php:

'driver' => array(
    __NAMESPACE__ . '_driver' => array(
        'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
        'cache' => 'array',
        'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Entity')
    ),
    'orm_default' => array(
        'drivers' => array(
            __NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
        )
    )
)

person hohner    schedule 21.02.2013    source источник
comment
Что производит orm:schema-tool:update --dump-sql? Также: учтите, что инструменты схемы DBAL выполняют самоанализ в одной базе данных за раз, так что это может быть проблемой здесь (известная)   -  person Ocramius    schedule 21.02.2013
comment
@Ocramius pastebin.com/DrtLHqsN. Немного отличается от того, что было раньше, когда я пытался - до того, как он пытался создать таблицы, существующие в users., в базу данных servers..   -  person hohner    schedule 21.02.2013
comment
@Ocramius Я также только что успешно обновил свою схему с помощью orm:schema-tool:update --force, но validate-schema все еще возвращает то же сообщение об ошибке базы данных.   -  person hohner    schedule 21.02.2013
comment
Можете ли вы также добавить конфигурацию сопоставления? Выдает ли orm:generate-proxies такое же исключение?   -  person Ocramius    schedule 21.02.2013
comment
Да, orm:generate-proxies показывает ту же ошибку. Что вы подразумеваете под конфигурацией отображения? Где это найти - в Module.php? Я подумал, что это может быть потому, что я динамически создавал EntityManagers в своем BaseController (с пользовательскими массивами соединений), которые я описал здесь. Но я создаю экземпляр для каждого модуля и все еще испытываю ту же проблему.   -  person hohner    schedule 21.02.2013
comment
Можешь сделать дамп $em->getMetadataFactory() для проверки драйверов?   -  person Ocramius    schedule 21.02.2013
comment
Это довольно большой фрагмент данных: sendspace.com/file/cc25po.   -  person hohner    schedule 21.02.2013
comment
@Ocramius Я также добавил конфигурацию драйвера для Doctrine, которая устанавливается в каждом из файлов module.config.php моего модуля.   -  person hohner    schedule 21.02.2013
comment
@Ocramius - удалось исправить :)   -  person hohner    schedule 22.02.2013


Ответы (1)


Мне удалось это исправить. В моем Server\Entity\Server у меня были эти функции получения/установки для добавления/удаления веб-сайтов:

public function setWebsite(Website $website) 
{
   $this->websites->add($website);    
}

public function removeWebsite(Website $website)
{
   $this->websites->removeElement($website);
}

Но вам нужно указать полное пространство имен в качестве аргумента:

public function setWebsite(\Client\Entity\Website $website) { ... }

Такая глупая ошибка! Я обнаружил проблему, потому что просмотрел каждый файл в трассировке стека и дошел до того, что он пытался сохранить каждый метод/аргумент в моем классе Entity в прокси-файле (строка 223ish в Doctrine/ORM/Proxy/ProxyFactory. php).

person hohner    schedule 22.02.2013
comment
Значит, фабрика прокси просто жаловалась на неправильное имя класса? Можете ли вы в конечном итоге проверить, стало ли сообщение об исключении лучше с мастером ORM? - person Ocramius; 22.02.2013
comment
Поскольку я не указал полное имя класса, он пытался создать их экземпляры в пространстве имен Server\Entity. Возможно, должен быть способ сопоставления функции получения/установки с отображением ассоциации (объявленным в аннотации Doctrine в верхней части файла), чтобы она знала, на что ссылаться. Сообщение об исключении всегда было одним и тем же (я не знаю, что вы подразумеваете под мастером ORM). Диагностика выглядит так долго, потому что я смотрел на сопоставление аннотаций вместо методов получения/установки - person hohner; 22.02.2013
comment
Да, это потому, что фабрике прокси нужно переписать методы: github.com/doctrine/common/blob/master/lib/Doctrine/Common/ . Насколько я знаю, мастер ORM (последний / крайний край) показывает специальное сообщение об ошибке для этого, поскольку я переписал эту часть. Сеттеры/геттеры не нуждаются в FQCN, если вы правильно импортируете классы с помощью оператора use - person Ocramius; 22.02.2013
comment
Да, теперь я это понимаю (утверждения use). У меня есть версия 2.3 Doctrine Common, потому что она была связана с модулем доктрины в Composer. Я вижу, вы были заняты переписыванием 2.4! сейчас установлю - person hohner; 22.02.2013
comment
только для проверки... он еще не помечен! :) - person Ocramius; 22.02.2013