首页 > 解决方案 > 如何使用 XML 或 YAML 而非注解映射来定义 Doctrine mappedSuperclass

问题描述

以下脚本来自https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/inheritance-mapping.html#mapped-superclasses,仅更改为包含第二个子类. 据我了解,MappedSuperclassBase它不能单独存在,必须由一个且只有一个子类(即EntitySubClassOneor 或EntitySubClassTwo)扩展,并且与 SQL 的超类型/子类型的概念相同。同意?

如何使用 YAML 或 XML 而不是注释映射来定义超级/子类型?

<?php
/** @MappedSuperclass */
class MappedSuperclassBase
{
    /** @Column(type="integer") */
    protected $mapped1;
    /** @Column(type="string") */
    protected $mapped2;
    /**
     * @OneToOne(targetEntity="MappedSuperclassRelated1")
     * @JoinColumn(name="related1_id", referencedColumnName="id")
     */
    protected $mappedRelated1;

    // ... more fields and methods
}

/** @Entity */
class EntitySubClassOne extends MappedSuperclassBase
{
    /** @Id @Column(type="integer") */
    private $id;
    /** @Column(type="string") */
    private $name;

    // ... more fields and methods
}

/** @Entity */
class EntitySubClassTwo extends MappedSuperclassBase
{
    /** @Id @Column(type="integer") */
    private $id;
    /** @Column(type="string") */
    private $name;

    // ... more fields and methods
}

标签: ormdoctrine-ormdoctrinesuperclasssupertype

解决方案


根据我们的评论,我想我看到了你的困惑。因为文档在同一页面上同时处理“MappedSuperclass”和“Discriminator”,所以我认为您在脑海中混淆了它们的用途。希望这可以帮助你:

  • AMappedSuperclass以可重用的方式提供属性/默认值,但它本身永远不能成为实体。这相当于 PHP 的abstract类(不能自己实例化)
  • 鉴别器提供了“扩展”实体的能力,使其成为另一个实体。例如,拥有一个Person实体会给你 1 个实体。该实体可以扩展,例如通过WorkerManager

a 的一个很好的用例MappedSuperclassAbstractEntity. 每个实体都需要一个 ID,一个唯一的标识符。它还为您提供了在 Listeners 等中检查的常见内容。所以,继续创建:

/**
 * @ORM\MappedSuperclass
 */
abstract class AbstractEntity
{
    /**
     * @var int
     * @ORM\Id
     * @ORM\Column(name="id", type="integer", options={"unsigned":true})
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;
  
    // getter / setter
}

看看这是如何声明abstractMappedSuperclass

这是因为 (abstract classMappedSuperclass) 都不能自己实例化。你不能这样做$entity = new AbstractEntity(),因为它是一个abstractPHP 类。Doctrine 也不会为AbstractEntity.

接下来,创建一个Person

/**
 * @ORM\Entity
 * @ORM\Table(name="persons")
 *
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 */
class Person extends AbstractEntity
{
    /**
     * @var string
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    protected $name;

    // getter / setter
}

以上, Person, Entity 是通过继承类型为Class Table Inheritance设置的。JOINED这意味着,在数据库级别,该表persons将与其他实体添加的任何列分开,扩展Person.

注意我没有声明DiscriminatorMap。以下来自文档,由我以粗体突出显示:

注意事项:

  • @InheritanceType、@DiscriminatorColumn 和 @DiscriminatorMap 必须在作为映射实体层次结构的一部分的最顶层类上指定。
  • @DiscriminatorMap 指定鉴别器列的哪些值将行标识为哪种类型。在上面的例子中,“person”值将一行标识为 Person 类型,“employee”将一行标识为 Employee 类型。
  • 如果类包含在与应用鉴别器映射的实体类相同的命名空间中,则鉴别器映射中的类的名称不需要完全限定。
  • 如果没有提供鉴别器图,则自动生成图。自动生成的鉴别器映射包含每个类的小写短名称作为键。

现在,让我们创建一个Worker

/**
 * @ORM\Entity
 * @ORM\Table(name="workers")
 */
class Worker extends Person
{
    /**
     * @var int
     * @ORM\Column(name="worker_id", type="integer", length=11, nullable=false)
     */
    protected $workerId;

    // getter / setter
}

所以,现在我们有了:

  • MappedSuperclass: AbstractEntity-不是一个独立的实体
  • 歧视:Person -一个独立的实体
  • “正常”:Worker -扩展 Person

注意事项:

  • 无法实例化MappedSuperclass 。因此:您不能创建与它的链接/关系。与 PHP 相媲美abstract class
  • 可识别实体是一个独立的实体,可以用作普通实体。您可以毫无问题地创建与它的关系
  • 扩展可识别实体的实体是两者的实例。在上面的代码中,这些都是正确的:$worker instanceof Worker并且$worker instanceof Person,因为Workerextends Person。然而,$person instanceof Workerfalse

$workerId = $person->getWorkerId() // generates "method does not exist" fatal

$workerId = $worker->getWorkerId() // generates integer value


希望设法为你清理东西。如果没有,请随时询问。


推荐阅读