Доктрина 2 Наследование конкретных таблиц с ассоциациями - PullRequest
4 голосов
/ 25 ноября 2011

Я прочитал Doctrine 2 Mapping с наследованием , но, если вам нужно, чтобы 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. Animal и Pet - это более или менее одно и то же. Если кто-нибудь что-то меняется в Animal, эти изменения не будут отражены в любые Pet подклассы.

Возможным решением первой проблемы было бы иметь дополнительную таблицу с именем pet, но все еще существует проблема с ассоциацией, поскольку столбец дискриминатора все еще находится в таблице animal и дублирует столбец в pet нарушит нормализацию.

enter image description here

1 Ответ

3 голосов
/ 28 ноября 2011

Я не уверен, что полностью понимаю вашу проблему, но я попробую:

  • A Pet, будучи Animal, имеет смысл сделатьэто явно в вашей иерархии классов .Обратите внимание, что abstract class Pet может подкласс concrete class Animal.Таким образом, вы все еще можете создать экземпляр Animal, Dog или Cat, но вы не можете создать экземпляр Pet;
  • Корневой класс Animal может иметь его собственное значение дискриминатора , что позволяет сохранить его с помощью Doctrine.Затем вы можете создать и сохранить Dog или Cat, и даже для общего 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 ( один к одному ).
...