Наследование таблиц классов Symfony/Doctrine и внешний ключ как первичный ключ

В настоящее время я разрабатываю веб-приложение с Symfony 2.5 (и Doctrine 2.4.2), которое должно быть гибким, чтобы легко подключать новые модули / пакеты.

Итак, у меня есть сущность (скажем, A), которая имеет две однозначные ассоциации с абстрактными классами (B и C). Будущие модули будут реализовывать один из двух абстрактных классов. Поскольку ассоциации являются однозначными, я сделал их идентификаторами абстрактных классов, чтобы упростить доступ к ним, когда мы знаем идентификатор экземпляра A

Вот как выглядит код:

класс А:

<?php

namespace Me\TestBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table()
 * @ORM\Entity
 */
class A
{
  /**
   * @ORM\Column(name="id", type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @ORM\OneToOne(targetEntity="B", cascade={"all"}, mappedBy="a")
   * @ORM\JoinColumn(name="id", referencedColumnName="a_id")
   */
  private $b;

  /**
   * @ORM\OneToOne(targetEntity="C", cascade={"all"}, mappedBy="a")
   * @ORM\JoinColumn(name="id", referencedColumnName="a_id")
   */
  private $c;
}

класс B:

<?php

namespace Me\TestBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table()
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 */
abstract class B
{
  /**
   * @ORM\Id
   * @ORM\OneToOne(targetEntity="A", inversedBy="b")
   * @ORM\JoinColumn(name="a_id", referencedColumnName="id")
   */
  private $a;
}

Я не буду публиковать код класса C, так как он такой же, как класс B.

На мой взгляд, вроде бы все хорошо. Даже для команды проверки соответствия. Действительно, когда я выполняю php app/console doctrine:schema:validate, он говорит мне, что моя схема действительна. Однако эта команда затем пытается сравнить мою схему со схемой в базе данных, и в этот момент она просто не работает. php app/console doctrine:schema:update --dump-sql терпит неудачу точно так же. Так что это довольно неловко, так как говорит мне, что моя схема действительна, но она не может использовать ее должным образом.

Ошибка:

[ErrorException]
Предупреждение: array_keys() ожидает, что параметр 1 будет массивом, значение NULL указано в /vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php строке 95

Ошибка появляется, как только я добавляю аннотации InheritanceType и DiscriminatorColumn к классам B и C. Дело в том, что она говорит мне, что моя схема действительна.

Так кто-нибудь знает, если я делаю что-то не так? Или это определенно ошибка в Doctrine? Есть ли у вас какие-либо идеи, которые бы принесли как минимум такую ​​же гибкость, как мое текущее решение?

Elioty

РЕДАКТИРОВАТЬ: я изменил сторону владения, чтобы быть абстрактными классами B и C, так как, в соответствии с документом, сторона владения - это сторона с внешним ключом и должна использовать атрибут inversedBy. Даже с этими изменениями моя схема все еще действительна, и та же самая ошибка все еще происходит.

РЕДАКТИРОВАТЬ 2: Если я создаю другое поле в B (и C) для хранения идентификатора сущности вместо взаимно-однозначного сопоставления, ошибка исчезает, но она больше не похожа на мою действительную схему.

РЕДАКТИРОВАТЬ 3: Я поговорил с членом команды разработчиков Doctrine, и он (и) сказал, что это определенно похоже на ошибку. Сообщить об ошибке здесь.

1 ответ

Прежде всего, команда php app/console doctrine:schema:validate проверяет правильность текущей схемы. Текущая схема - это схема, сгенерированная вашей последней вызванной командой php app/console doctrine:schema:update --force

С другой стороны, команда php app/console doctrine:schema:update --dump-sql не выполняет фактическое обновление схемы, хотя могут обнаруживаться некоторые ошибки, другие не будут появляться...

Я не понимаю класс B. Идентификационные данные этого (абстрактного) класса являются отношениями OneToOne? В любом случае, дело в том, что Doctine будет игнорировать @ORD\Id, если вы не добавите определенияиратский тип. Когда вы добавляете это определение в формате garitanceType, Doctrine сделает атрибут "a" первичным ключом B. Также он создаст еще один атрибут с именем "a_id", который будет служить внешним ключом для будущих подклассов (расширений B). Но... отношения не наследуются.

Надеюсь это поможет...

Другие вопросы по тегам