Доктрина 2 Наследование конкретных таблиц с ассоциациями
Я прочитал Doctrine 2 Inheritance Mapping с Ассоциацией, но скажите, если вам нужно Animal
быть самостоятельной сущностью, скажем, для создания списков опций.
В этом случае столбец дискриминатора для Pet
находится в колонке видов в animal table
,
Так что классы будут примерно такими.
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
}
Я вижу пару проблем.
animal
таблица не имеет внешнего ключа кowner
, Так что$pets
Ассоциация не собирается работать.Animal
а такжеPet
более или менее то же самое. Если кто-то что-то меняет вAnimal
эти изменения не будут отражены ни в одномPet
подклассы.
Возможным решением первой проблемы было бы иметь дополнительную таблицу с именем pet
, но есть еще проблема с ассоциацией, потому что столбец дискриминатора все еще находится в animal
таблица и дублирование столбца в pet
нарушит нормализацию.
1 ответ
Я не уверен, что полностью понимаю вашу проблему, но я попробую:
Pet
бытьAnimal
, имеет смысл сделать это явным в вашей иерархии классов. Обратите внимание, что абстрактный классPet
может подкласс конкретного класса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
стол (один на один).