如何使用 XML 或 YAML 而不是注释映射来定义 Doctrine mappedSuperclass

How to define a Doctrine mappedSuperclass using XML or YAML instead of annotation mapping

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

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

<?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
}

根据我们的评论,我想我明白了你的困惑。因为 the docs 在同一个页面上同时处理“MappedSuperclass”和“Discriminator”,我想你已经在脑海中混淆了它们的用途。希望这可以帮助你:

  • A MappedSuperclass 以可重复使用的方式提供 properties/defaults,但它永远不能单独成为一个实体。这相当于 PHP 的 abstract classes(不能自己实例化)
  • 判别器提供了“扩展”实体的能力,使其成为另一个实体。例如,拥有一个 Person 实体会给您 1 个实体。该实体可以扩展,例如 WorkerManager.

MappedSuperclass 的一个很好的用例是 AbstractEntity。每个实体都需要一个 ID,一个唯一的标识符。它还为您提供了一些常见的检查听众等。所以,继续创建:

/**
 * @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(),因为它是 abstract PHP class。 Doctrine 也不会为 AbstractEntity.

创建单独的 table

接下来,创建一个 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,通过 JOINED 继承类型为 Class Table Inheritance 设置实体。这意味着,在数据库级别,table persons 将与其他实体添加的任何列分开,扩展 Person.

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

Things to note:

  • The @InheritanceType, @DiscriminatorColumn and @DiscriminatorMap must be specified on the topmost class that is part of the mapped entity hierarchy.
  • The @DiscriminatorMap specifies which values of the discriminator column identify a row as being of which type. In the case above a value of "person" identifies a row as being of type Person and "employee" identifies a row as being of type Employee.
  • The names of the classes in the discriminator map do not need to be fully qualified if the classes are contained in the same namespace as the entity class on which the discriminator map is applied.
  • If no discriminator map is provided, then the map is generated automatically. The automatically generated discriminator map contains the lowercase short name of each class as key.

现在,让我们创建一个 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 不能 实例化。因此:您 不能 为它创建 links/relations。与PHP的abstract class
  • 相当
  • 受歧视实体是独立存在的实体,可以用作普通实体。您可以毫无问题地与它建立关系
  • 扩展受歧视实体的实体是两者的实例。在上面的代码中,它们都是真的:$worker instanceof Worker$worker instanceof Person,因为 Worker 扩展了 Person。但是,$person instanceof Worker 将是 false!

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

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


希望能为您解决问题。如果没有,请随时询问。