orm - 如何使用 XML 或 YAML 而非注解映射来定义 Doctrine mappedSuperclass
问题描述
以下脚本来自https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/inheritance-mapping.html#mapped-superclasses,仅更改为包含第二个子类. 据我了解,MappedSuperclassBase
它不能单独存在,必须由一个且只有一个子类(即EntitySubClassOne
or 或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
}
解决方案
根据我们的评论,我想我看到了你的困惑。因为文档在同一页面上同时处理“MappedSuperclass”和“Discriminator”,所以我认为您在脑海中混淆了它们的用途。希望这可以帮助你:
- A
MappedSuperclass
以可重用的方式提供属性/默认值,但它本身永远不能成为实体。这相当于 PHP 的abstract
类(不能自己实例化) - 鉴别器提供了“扩展”实体的能力,使其成为另一个实体。例如,拥有一个
Person
实体会给你 1 个实体。该实体可以扩展,例如通过Worker
和Manager
。
a 的一个很好的用例MappedSuperclass
是AbstractEntity
. 每个实体都需要一个 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
}
看看这是如何声明abstract
的MappedSuperclass
?
这是因为 (abstract class
和MappedSuperclass
) 都不能自己实例化。你不能这样做$entity = new AbstractEntity()
,因为它是一个abstract
PHP 类。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
,因为Worker
extendsPerson
。然而,$person instanceof Worker
会false
!
$workerId = $person->getWorkerId() // generates "method does not exist" fatal
$workerId = $worker->getWorkerId() // generates integer value
希望设法为你清理东西。如果没有,请随时询问。
推荐阅读
- python - Mac OS X预装的python2.7中这三个“python”有什么区别?
- laravel - Laravel 从关系中过滤数据
- r - 更改列名时出错,名称的属性 [1] 必须与向量 [0] 的长度相同
- python - Python venv 文件夹究竟是如何工作的?我的项目使用依赖于这个 venv 文件夹使用不同的 Python 版本执行项目?
- mysql - 如何根据另一列中的 IF 参数从 SQL 中的一列创建两列
- javascript - 如何从也具有非数组元素的数组中删除数组元素
- aem - 是否可以通过 QueryBuilder API 根据尺寸搜索图像的再现
- shell - 将表格文件转换为 HTML 表格
- xamarin.forms - WhenAnyValue 没有被 RaisePropertyChanged 调用
- prolog - Prolog - 连接图初学者