Symfony/Doctrine 类表继承和外键作为主键

Posted

技术标签:

【中文标题】Symfony/Doctrine 类表继承和外键作为主键【英文标题】:Symfony/Doctrine class table inheritance and foreign key as primary key 【发布时间】:2014-06-17 13:55:09 【问题描述】:

我目前正在使用 Symfony 2.5(和 Doctrine 2.4.2)设计一个 Web 应用程序,它必须灵活地轻松插入新的模块/捆绑包。

所以我有一个实体(比如说 A),它与抽象类(B 和 C)有两个一对一的关联。未来的模块将实现两个抽象类之一。由于关联是一对一的,因此我将它们设为抽象类的 ID,以便在我们知道 A 实例的 ID 时轻松访问它们

下面是代码的样子:

A 类:

<?php

namespace Me\TestBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table()
 * @ORM\Entity
 */
class A

  /**
   * @ORM\Column(name="id", type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @ORM\OneToOne(targetEntity="B", cascade="all", mappedBy="a")
   * @ORM\JoinColumn(name="id", referencedColumnName="a_id")
   */
  private $b;

  /**
   * @ORM\OneToOne(targetEntity="C", cascade="all", mappedBy="a")
   * @ORM\JoinColumn(name="id", referencedColumnName="a_id")
   */
  private $c;

B 类:

<?php

namespace Me\TestBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table()
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 */
abstract class B

  /**
   * @ORM\Id
   * @ORM\OneToOne(targetEntity="A", inversedBy="b")
   * @ORM\JoinColumn(name="a_id", referencedColumnName="id")
   */
  private $a;

C类的代码我就不贴了,因为它和B类是一样的。

在我看来,一切似乎都很好。即使对于映射验证命令。 事实上,当我执行php app/console doctrine:schema:validate 时,它告诉我我的架构是有效的。但是,此命令然后尝试将我的架构与数据库中的架构进行比较,但此时它只是失败了。 php app/console doctrine:schema:update --dump-sql 以完全相同的方式失败。所以这很尴尬,因为它告诉我我的架构是有效的,但它不能正确使用它。

错误:

[错误异常] 警告:array_keys() 期望参数 1 是数组,在 /vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php 第 95 行中给出了 null

当我将 InheritanceType 和 DiscriminatorColumn 注释添加到类 B 和 C 时,错误就会出现。事情是它告诉我我的架构是有效的。

如果我做错了什么,有人知道吗?或者它绝对是 Doctrine 中的一个错误?您是否有任何其他想法可以带来至少与我目前的解决方案一样多的灵活性?

艾略蒂

编辑:我将拥有方更改为抽象类 B 和 C,因为根据文档,拥有方是具有外键的一方,并且必须使用 inversedBy 属性。即使进行了这些更改,我的架构仍然有效,并且仍然会发生相同的错误。

EDIT2:如果我在 B(和 C)中创建另一个字段来保存实体的身份而不是一对一关联,错误就会消失,但它不再像我的 有效 架构。

EDIT3:我与 Doctrine 开发团队的一位成员聊天,他告诉我这绝对看起来像一个错误。 Bug report here.

【问题讨论】:

【参考方案1】:

首先,php app/console doctrine:schema:validate 命令检查当前模式的有效性。当前架构是您上次调用命令php app/console doctrine:schema:update --force 生成的架构@

另一方面,php app/console doctrine:schema:update --dump-sql 命令不会对架构执行实际更新,尽管它可能会发现一些错误,而其他一些则不会出现...

我不明白B类。这个(抽象)类的身份是OneToOne关系?无论如何,如果您不添加继承类型定义,Doctine 将忽略 @ORD\Id。当您添加此继承类型定义时,Doctrine 将使属性“a”成为 B 的主键。它还将创建另一个名为“a_id”的属性,该属性将用作未来子类(B 的扩展)的外键。但是...关系不是继承的。

希望这会有所帮助...

【讨论】:

以上是关于Symfony/Doctrine 类表继承和外键作为主键的主要内容,如果未能解决你的问题,请参考以下文章

Symfony 2 + Doctrine 2 + PHPUnit 3.5:闭包异常的序列化

与复合唯一约束的关系(symfony + 学说)

Symfony 5(Doctrine 2.9),Doctrine 不会为 ManyToOne 自引用关系生成迁移

Symfony2\Doctrine - 检索用户角色

如何在 Symfony 2 / Doctrine 中启用 ENUM

Symfony - Doctrine 实体的返回类型