将子类映射为其扩展父类

Posted

技术标签:

【中文标题】将子类映射为其扩展父类【英文标题】:Map subclass as its extended parent 【发布时间】:2015-09-16 08:20:07 【问题描述】:

我创建了以下抽象类,它使用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 下面的类的类都被映射为扩展上抽象类的类)。

这可能吗?

【问题讨论】:

如果你在某处提到这是 Doctrine 2 可能会有所帮助(如果是...) @markdwhite doctrine2 是标签之一 【参考方案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);

进一步阅读

另外,请查看 Doctrine 手册中的 php mapping section 以及更多信息的 API docs ClassMetadataBuilder

【讨论】:

【参考方案2】:

答案可能在 Doctrine Docs 上:

“应在@DiscriminatorMap 中指定属于映射实体层次结构(包括最顶层的类)的所有实体类”

http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html

您只指定了 GreenEntity 和 BlueEntity。

我不知道我在说什么。这是我读到的关于 Doctrine 的第一本书……

【讨论】:

我只指定了 GreenEntity 和 BlueEntity,因为我只希望 AbstractEntity 映射(了解)它们。扩展它们的类位于库中,因此核心应用程序的某些实例使用它们,有些则不使用。我希望 AbstractEntity 对扩展其子类的类完全不可知,同时仍然能够通过将它们映射为父类来扩展它们。 @ManeatingKoala - 我真的不知道,我想在没有其他回应的情况下尝试提供帮助。所以我就这样吧。

以上是关于将子类映射为其扩展父类的主要内容,如果未能解决你的问题,请参考以下文章

子类继承父类后想要扩展父类方法

python--继承--方法的重写---和父类的扩展

知识点总结

SV中父类与子类句柄转换,即子类的扩展类与父类句柄转换等问题

SV中父类与子类句柄转换,即子类的扩展类与父类句柄转换等问题

SV中父类与子类句柄转换,即子类的扩展类与父类句柄转换等问题