Doctrine2多级继承

时间:2017-01-04 08:06:58

标签: php inheritance doctrine-orm

我一直在尝试使用doctrine2映射多级继承,这里是UML: enter image description here

每个类都映射一个SQL表,映射如下所示:

   /**
     * @Entity
     * @Table(name="PERSONS")
     * @InheritanceType("JOINED")
     * @DiscriminatorColumn(name="PERSON_TYPES", type="string")
     * @DiscriminatorMap({"INSUREE" = "Insuree", "ADMIN" = "Admin"})
     */
    abstract class Person extends Entity{}

    /**
     * @Entity
     * @Table(name="INSUREES")
     * @InheritanceType("JOINED")
     * @DiscriminatorColumn(name="INSUREE_TYPES", type="string")
     * @DiscriminatorMap({"CUSTOMER" = "Customer", "THIRD_PARTY" = "ThirdParty"})
     */
    abstract class Insuree extends Person{}

    /**
     * @Entity
     * @Table(name="ADMINS")
     */
    final class Admin extends Person implements User{}

    /**
     * @Entity
     * @Table(name="CUSTOMERS")
     */
    final class Customer extends Insuree implements User{}

    /**
     * @Entity
     * @Table(name="EXPERTS")
     */
    final class Expert extends Person{}

当我试图找到所有客户或任何其他具体类时,我收到了这个错误:

  

未捕获的Doctrine \ Instantiator \ Exception \ InvalidArgumentException:提供的类" Insuree"是抽象的,不能在......中实例化。

我在github上找到了一个项目,其映射层次结构与我的相似,并且工作正常:

https://github.com/paulandrieux/MultipleInheritanceSandbox/tree/master/src/Acme/DemoBundle/Entity

编辑:

将所有鉴别器放到顶级类(Person)后,当我尝试保留新客户时,Doctrine会跳过将数据插入INSUREES表,因为我收到此错误:

  

执行' INSERT INTO CUSTOMERS(ID,ID_CARD,SEPA)VALUES(?,?,?)' with params [10,"",""]:SQLSTATE [23000]:完整性约束违规:1452无法添加或更新子行:外键约束失败({{ 1}}。aaa,CONSTRAINT customers FOREIGN KEY(customers_ibfk_1)参考IDINSUREES)ON DELETE CASCADE)"

这是我的CREATE TABLE sql脚本:

ID

1 个答案:

答案 0 :(得分:2)

您只能在最上层的班级Doctrine class-table-inheritance中定义InheritanceType,DiscriminatorColumn和DiscriminatorMap,在您的情况下

我建议如下:

   /**
     * @Entity
     * @Table(name="PERSONS")
     * @InheritanceType("JOINED")
     * @DiscriminatorColumn(name="PERSON_TYPES", type="string")
     * @DiscriminatorMap({
            "INSUREE" = "Insuree", 
            "ADMIN" = "Admin",
            "CUSTOMER" = "Customer",
            "EXPERT" = "Expert"
        })
     */
    abstract class Person extends Entity{}

    /**
     * @Entity
     * @Table(name="INSUREES")
     */
    abstract class Insuree extends Person{}

更新

您的数据库方案应如下所示: database-scheme 其中 interface_task 是您案例中的人。你对所有的子类(和子子类)都这样做,都指向超类,而id是指向超类interface_task(在你的情况下是人)的id的外键

同样可以肯定的是,你在外键上添加了一个on-delete级联,这样如果你删除了一个子类,数据库中的父类也会被删除