【问题标题】: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 是标签之一

标签: php oop orm doctrine-orm discriminator


【解决方案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 - 我真的不知道,我想在没有其他回应的情况下尝试提供帮助。所以我就这样吧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    相关资源
    最近更新 更多