Doctrine2中是否有任何关于在抽象类上使用@Entity注释或将抽象类放入鉴别器映射中的禁忌症?



我没有找到这方面的信息。

很多人告诉我,把@Entity注释放在抽象类上是无稽之谈。从我的角度来看,当我创建一个PHP抽象类时,我主要希望没有PHP代码可以使用new运算符创建实例。

有些人告诉我在像 ChildrenAbstract 这样的类上使用@MappedSuperClass,但除非我删除@Entity似乎无用的注释,因为我有时需要@MappedSuperClass不允许的映射。

很多人问我为什么,所以这里基本上是为什么:

家长摘要.php

/**
* @ORMTable(name="ParentAbstract")
* @ORMEntity(repositoryClass="AppRepositoryParentAbstractRepository")
* @ORMInheritanceType("JOINED")
* @ORMDiscriminatorColumn(name="discr", type="string")
* @ORMDiscriminatorMap({"childrenAbstract" = "ChildrenAbstract", "concreteA" = "ConcreteA", "concreteB" = "ConcreteB"})
*/
abstract class ParentAbstract
{
...
}

儿童摘要.php

/**
* @ORMTable(name="ChildrenAbstract")
* @ORMEntity(repositoryClass="AppRepositoryChildrenAbstractRepository")
*/
abstract class ChildrenAbstract extends ParentAbstract
{   
/** * @ORMColumn(type="string", nullable=true) */
private $picture;
}

混凝土A.php

/**
* @ORMTable(name="ConcreteA")
* @ORMEntity(repositoryClass="AppRepositoryConcreteARepository")
*/
class ConcreteA extends ChildrenAbstract
{   
...
}

混凝土B.php

/**
* @ORMTable(name="ConcreteB")
* @ORMEntity(repositoryClass="AppRepositoryConcreteBRepository")
*/
class ConcreteB extends ChildrenAbstract
{   
...
}

儿童抽象控制器.php

class ChildrenAbstractController extends AbstractController
{   
/**
* @Route("/home/childrenabstract/get/picture/{id}", name="get_childrenabstract_picture")
*/
public function getChildrenAbstractPicture(Request $request, int $id) : Response
{
$childrenAbstract = $this->getDoctrine()->getRepository(ChildrenAbstract::class)->findById($id);
if(!$childrenAbstract)
{
throw new Exception("childrenAbstract don't exists !");
}
$response = new BinaryFileResponse("../path/".$childrenAbstract->getId()."/".$childrenAbstract->getPicture());
$response->headers->set('Content-Type', 'image/' . 'png');
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE);
return $response;
}    

ConcreteAFront.html.twig

{% for concreteA in container.concreteAs %}
<td>{{ form_label(form.picture) }}</td><td><img src="{{ path('get_childrenabstract_picture', {id:concreteA.id}) }}" /></td>
{% endfor %}

ConcreteBFront.html.twig

{% for concreteB in container.concreteBs %}
<td>{{ form_label(form.picture) }}</td><td><img src="{{ path('get_childrenabstract_picture', {id:concreteB.id}) }}" /></td>
{% endfor %}

我需要一条"通用"路线来与混凝土结构的某些部分进行交互,有时 AbctractChildren 中的映射.php@ORM\ManyToOne、@ORM\ManyToMany、...

关键是这是完美的工作。或者这似乎非常有效。我需要确保 Doctrine2 旨在支持这种方式,或者是否是一种需要避免的不良做法。

TL;DR:避免将实体注释放在抽象类上。首先,它不寻常,可能会让未来的维护者感到困惑。其次,它违背了教义预期的工作方式,因此可能会在未来的教义版本中停止工作。

问得好!让我们去看文档。从"基本映射"部分:

。Doctrine 只知道您的实体,因为您将使用映射元数据来描述它们的存在和结构,映射元数据是告诉 Doctrine 您的实体应如何存储在数据库中的配置。

在没有附加信息的情况下,Doctrine 期望将实体保存到与我们案例中的 Message 中的类同名的表中。

以及从继承映射部分:

映射

超类是一个抽象或具体的类,它为其子类提供持久实体状态和映射信息,但它本身不是实体。通常,此类映射超类的用途是定义多个实体类共有的状态和映射信息。

因此,教义期待两件事:

  1. 批注为@Entity的类将作为对象进行操作,每个对象表示表中的一行数据。
  2. 注释为@MappedSuperclass的类不会作为对象,也不会表示一行数据

根据定义,abstract class不能属于类别 #1,因此它必须只适合类别 #2。无论如何,这就是理论。实际上,你正在寻找重用,这是MappedSuperclass的工作。一定要使用它,这就是为什么教义使这成为可能!

您表示您在实现 MappedSuperclass 和关系时遇到了问题,我猜您遇到了如下错误:

[Doctrine\ORM\Mapping\MappingException] 将反边一对多或多对多关联放在 映射的超类"应用...\AbstractFoo#thing'.

发生这种情况是由于语言实现限制,可以通过将属性从private打开到protected来修复。

如果您遇到其他问题,请发布。如果 Mappedsuperclass 不能用于处理你的用例,那么你的特定用例要么非常独特,要么它是 Doctrine 中的一个错误。无论哪种方式,它都值得进一步评估。

最新更新