我目前正在设计一个web应用程序与Symfony 2.5(和Doctrine 2.4.2),必须灵活,方便地插入新的模块/包。
所以我有一个实体(假设A),它与抽象类(B和C)有两个一对一的关联。未来的模块将实现两个抽象类中的一个。由于关联是一对一的,所以我将它们作为抽象类的ID,以便在我们知道A的实例ID时方便地访问它们
代码是这样的:
A类:
<?php
namespace MeTestBundleEntity;
use DoctrineORMMapping as ORM;
/**
* @ORMTable()
* @ORMEntity
*/
class A
{
/**
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORMOneToOne(targetEntity="B", cascade={"all"}, mappedBy="a")
* @ORMJoinColumn(name="id", referencedColumnName="a_id")
*/
private $b;
/**
* @ORMOneToOne(targetEntity="C", cascade={"all"}, mappedBy="a")
* @ORMJoinColumn(name="id", referencedColumnName="a_id")
*/
private $c;
}
B类:
<?php
namespace MeTestBundleEntity;
use DoctrineORMMapping as ORM;
/**
* @ORMTable()
* @ORMEntity
* @ORMInheritanceType("JOINED")
* @ORMDiscriminatorColumn(name="discr", type="string")
*/
abstract class B
{
/**
* @ORMId
* @ORMOneToOne(targetEntity="A", inversedBy="b")
* @ORMJoinColumn(name="a_id", referencedColumnName="id")
*/
private $a;
}
我将不发布C类的代码,因为它与b类相同。
在我看来,一切似乎都很好。即使是映射验证命令。实际上,当我执行php app/console doctrine:schema:validate
时,它告诉我我的模式是有效的。然而,这个命令会尝试将我的模式与数据库中的模式进行比较,但它会失败。php app/console doctrine:schema:update --dump-sql
以同样的方式失效。所以这是相当尴尬的,因为它告诉我我的模式是有效的,但它不能正确地使用它。
错误:
[ErrorException]
警告:array_keys()期望参数1为array, null在/vendor/doctrine/dbal/lib/doctrine/dbal/Schema/Index.php第95行
当我将InheritanceType和DiscriminatorColumn注释添加到类B和c时,错误就出现了。事情是它告诉我我的模式是有效的。
所以有人有任何线索,如果我做错了什么?或者这绝对是教条中的错误?你有什么其他的主意能带来至少和我现在的方案一样多的灵活性吗?
Elioty
编辑:我将拥有方更改为抽象类B和C,因为根据文档,拥有方是具有外键的一方,必须使用inversedBy属性。即使做了这些修改,我的模式仍然有效,同样的错误仍然发生。
EDIT2:如果我在B(和C)中创建另一个字段来保存实体的身份,而不是一对一的关联,错误就会消失,但它不再像我的有效的模式。
编辑3:我和Doctrine开发团队的一个成员聊了聊,他告诉我这看起来肯定像个bug。
首先,php app/console doctrine:schema:validate
命令检查当前模式的有效性。当前模式是您最后一次调用命令php app/console doctrine:schema:update --force
另一方面,php app/console doctrine:schema:update --dump-sql
命令不执行对模式的实际更新,尽管它可能会发现一些错误,但其他一些不会出现…
我不理解类b。这个(抽象)类的身份是一个OneToOne关系?无论如何,问题是,如果您不添加inheritanceType定义,Doctine将忽略@ORDId。当你添加这个继承类型定义教条将使属性'a'的主键B.此外,它将创建另一个名为'a_id'的属性,这将作为一个外键为未来的子类(扩展B)。关系不能被继承。