如何与 MappedSuperclass 作品建立联系?

How to make relation to MappedSuperclass works?

我在 Symfony 5 中遇到多对一与 MappedSuperclass 的关系问题。我有实体 Employee,Employer 扩展了 MappedSuperclass abstract class Person。我想创建与人(员工和雇主)相关的 raports 实体,如下所示:

    /**
     * @ORM\ManyToOne(targetEntity=Person::class)
     */
    private $person;

但是当我尝试推送迁移时,我收到以下错误消息:

Column name id referenced for relation from App\Entity\Raport towards App\Entity\Person does not exist.

但我在这些 classes:

中有 id 属性
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    protected $id;

我在 Symfony 页面示例中找到了创建界面来执行此操作,但它对我也不起作用。也许有人以前遇到过这个问题并且知道如何解决它。非常感谢您的回复。

编辑 我的人 class:

**
 * Abstract base class to be extended by my entity classes with same fields
 *
 * @MappedSuperclass
 */
abstract class Person
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    protected $id; //This property exist in Employee and Employer too (like doctrine documentation said)

现在,当我尝试创建 Employee 或 Employer 时,将它从 superclass 更改为 'JOINED' 继承时,出现以下错误:

An exception occurred while executing 'INSERT INTO person (discr) VALUES  
   (?)' with params ["Employee"]:                                                  

  SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error i  
  n your SQL syntax; check the manual that corresponds to your MySQL server v  
  ersion for the right syntax to use near 'person (discr) VALUES ('Employee')'  
   at line 1        

没有任何其他方法可以仅在一个 属性 中与实现一个接口或扩展 class 的少数实体建立关系?有时我讨厌教条......我的个人实体可能有助于配置错误:

* @ORM\Entity(repositoryClass=PersonRepository::class)
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({"person" = "Person", "employee" = "Employee", "employer" = "Employer"})
 */
class Person
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    protected $id;

    public function getId(): ?int
    {
        return $this->id;
    }

}

尝试删除摘要。我没有 MappedSuperclass 作为关系。我在项目中设置了 MappedSuperclass is abstract for a class,但出现错误。摘要class好像不行。这也是有道理的,因为它不是那种意义上的抽象 class。

您不能将关系目标设为 MappedSuperClass,因为它本身不是实体。它只能自己定义一个拥有的一对一关系(或非常有限的多对多):

A mapped superclass cannot be an entity, it is not query-able and persistent relationships defined by a mapped superclass must be unidirectional (with an owning side only). This means that One-To-Many associations are not possible on a mapped superclass at all. Furthermore Many-To-Many associations are only possible if the mapped superclass is only used in exactly one entity at the moment. For further support of inheritance, the single or joined table inheritance features have to be used.

source: https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/inheritance-mapping.html#mapped-superclasses

可能想要的是单一table继承或classtable继承(参见上面的link,它也显示了这些)。虽然它会变得很烦人。您已收到警告。

可以与 MappedSuperClass 建立关系(在 Symfony 中)。你想要的是动态映射,没有很好的记录。你必须使用 Doctrine Event loadClassMetadata。文档示例非常(非常)简单,但您可以做更多。

在您的情况下,您必须检查实体是否是您想要的实体并且不是 MappedSuperClass:

<?php

namespace App\Doctrine;

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Events;

class LoadClassMetadataListener implements EventSubscriber
{
    public function getSubscribedEvents()
    {
        return [
            Events::loadClassMetadata,
        ];
    }

    public function loadClassMetadata(\Doctrine\ORM\Event\LoadClassMetadataEventArgs $eventArgs)
    {
        $metadata = $eventArgs->getClassMetadata();
        $class = new \ReflectionClass($metadata->getName());

        if ($class->implementsInterface('Your\Interface') && !$metadata->isMappedSuperclass) {
            $metadata->mapManyToOne(array(
                'targetEntity'  => Person::class,
                'fieldName'     => 'person',
                'inversedBy'    => 'whatYouWant',
                'joinColumns'   => [[
                    'name'                 => 'xxx_id',
                    'referencedColumnName' => 'id',
                    'nullable'             => false,
                ]]
            ));
        }
    }
}
services:
    App\Doctrine\LoadClassMetadataListener
        tags:
            - { name: doctrine.event_subscriber }

$metadata 可以访问所有映射可能性和所有映射选项,例如注释、yaml 或 XML.