Doctrine 2具有关联的具体表继承

时间:2011-11-25 10:14:23

标签: php inheritance orm doctrine-orm concrete-inheritance

我已阅读Doctrine 2 Inheritance Mapping with Association但请说明您是否需要Animal作为一个实体,比如创建选项列表。

在这种情况下,Pet的判别列位于animal table的种类列中。

Pet Database Schema

所以课程就是这样的。

class Animal
{
    $id;
    $species;
}

/**
 * @Table(name="animal")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="species", type="string")
 * @DiscriminatorMap({"dog" = "Dog", "cat" = "Cat"})
 */
abstract class Pet
{
    $id
    $species;
}

class Dog extends Pet { }

class Cat extends Pet { }

class Owner 
{
    /**
     * @OneToMany(targetEntity="Pet")
     */
    $pets
}

我看到了一些问题。

  1. animal表没有owner的外键。所以 $pets关联不起作用。

  2. AnimalPet或多或少都是一样的。如果有的话 更改Animal中的内容,这些更改不会反映在其中 任何Pet子类。

  3. 第一个问题的一个可能的解决方案是有一个名为pet的额外表,但关联仍然存在问题,因为鉴别器列仍然在animal表中并且重复pet中的列会破坏规范化。

    enter image description here

1 个答案:

答案 0 :(得分:3)

我不确定完全理解你的问题,但我会试一试:

  • PetAnimal在您的类层次结构中明确显示是有意义的。请注意, abstract Pet可以继承具体Animal。这样,您仍然可以实例化AnimalDogCat,但无法实例化Pet;
  • Animal根类可以具有自己的鉴别器值,这样可以使用Doctrine持久化它。然后,您可以创建并保留DogCat,甚至是通用Animal;
  • Animal需要对其所有者的引用;
  • Owner现在与Animal之间存在一对多关系;
  • species列是一个鉴别器,并且没有值添加到您的域模型(类名称会告诉您正在处理的Animal,所以我建议删除这个属性。

最后说明,你真的需要一个Pet课吗?如果一个宠物没有特定的Animal(即该类是空的),那么你应该从你的类层次结构中删除它。

class Owner {
    /**
     * @OneToMany(targetEntity="Animal")
     */
    protected $animals;
}

/**
 * @Table(name="animal")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="species", type="string")
 * @DiscriminatorMap({"animal" = "Animal", "dog" = "Dog", "cat" = "Cat"})
 */
class Animal {
    /** @Id @Column(type="integer") @GeneratedValue */
    protected $id;

    /** @ManyToOne(targetEntity="Owner") */
    protected $owner;
}

abstract class Pet extends Animal {
    // Do you really need this class?
}

class Dog extends Pet {
    // ...
}

class Cat extends Pet {
    // ...
}

关于您的数据库结构,我建议进行以下更改:

  • owner_id&移动Dog Cat表格Animal;
  • animal_id&中删除Dog Cat个表格;他们将与id表(一对一)共享Animal值。