Я создал следующий абстрактный класс, который использует наследование одной таблицы и карты подклассов на DiscriminatorColumn model
,
/**
* @Entity
* @Table(name="entity")
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="model", type="string")
* @DiscriminatorMap({
* "green" = "model\GreenEntity",
* "blue" = "model\BlueEntity"* })
*/
abstract class AbstractEntity
{
/** @Id @Column(type="string") */
protected $entity_id;
}
Допустим, я расширяю абстрактный класс AbstractEntity
по некоторым классам:
class GreenEntity extends AbstractEntity {}
class BlueEntity extends AbstractEntity {}
И расширить их еще на несколько подклассов
class GreenEntityChildOne extends GreenEntity {}
class GreenEntityChildTwo extends GreenEntity {}
class BlueEntityChildOne extends BlueEntity {}
class BlueEntityChildTwo extends BlueEntity {}
Теперь, например, когда я создаю экземпляр GreenEntityChildOne
и сохранить его в базе данных, он выдаст исключение, что у меня нет сопоставления для него.
То, что я пытаюсь сделать, это получить GreenEntityChildOne
отображаться как GreenEntity
(точнее, каждый класс, который расширяет класс ниже AbstractEntity
отображаться как класс, который расширяет верхний абстрактный класс).
Это вообще возможно?
Да, сопоставление, которого вы пытаетесь достичь, возможно. Однако не с чистыми аннотациями. Важно то, что доктрина должна знать все подклассы во время выполнения. Если вы не хотите явно указывать их в аннотациях сопоставленного суперкласса, вам нужно будет предоставить их динамически.
На блоге есть отличный пост динамическое отображение с Doctrine, который объясняет, как вы можете использовать обработчики событий Doctrine для программного изменения загруженного ClassMetadata
,
Чтобы динамически добавлять подклассы в карту дискриминатора, вы можете реализовать прослушиватель событий Doctrine, например:
class DynamicDiscriminatorMapSubscriber implements EventSubscriber
{
public function getSubscribedEvents()
{
return array(Events::loadClassMetadata);
}
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$metadata = $eventArgs->getClassMetadata();
$metadata->addDiscriminatorMapClass("GreenEntityChildOne", GreenEntityChildOne::class);
}
}
Теперь вам нужно всего лишь зарегистрировать подписчика на событие в Doctrine. В идеале вы должны добавить классы, которые хотите добавить, на основе вашей конфигурации подписчику на событие.
// create dynamic subscriber based on your config which contains the classes to be mapped
$subscriber = new DynamicDiscriminatorMapSubscriber($config);
$entityManager->getEventManager()->addEventSubscriber($subscriber);
Кроме того, посмотрите на PHP картографический раздел в руководстве по доктрине и тем более информативным API документы для ClassMetadataBuilder
,
Ответ, возможно, на Доктрине Docs:
«Все классы сущностей, являющиеся частью отображенной иерархии сущностей (включая самый верхний класс), должны быть указаны в @DiscriminatorMap»
http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html
Вы указали только GreenEntity и BlueEntity.
Я не знаю о чем говорю. Это первое, что я когда-либо читал о Доктрине …