我创建了以下抽象类,它使用single table inheritance并在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
以下类的每个类都要映射为扩展的类上层抽象类)。
这一切都可能吗?
答案 0 :(得分:1)
是的,您尝试实现的映射是可能的。但是,不是纯注释。重要的是Doctrine需要在运行时知道所有子类。如果您不想在映射的超类的注释中明确声明它们,则需要动态提供它们。
dynamic mapping with 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 mapping section以及ClassMetadataBuilder
提供的信息量更多API docs。
答案 1 :(得分:0)
答案可能在Doctrine Docs上:
“应该在@DiscriminatorMap”中指定属于映射实体层次结构(包括最顶层类)的所有实体类“
http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html
您只指定了GreenEntity和BlueEntity。
我不知道我在说什么。这是我读过关于教义的第一件事......