Я использую Doctrine2 для управления моей моделью ниже: существует абстрактная концепция Content
with Composite pattern в Gallery
, а также абстрактная концепция Media
из которой наследуются Video
и Image
.
Мой выбор заключался в том, чтобы добавить дискриминаторов в таблицы Content
и Media
, чтобы различать Gallery
, Video
и Image
. Content
использует JOIN inheritance
а Media
использует SINGLE_TABLE inheritance
.
Когда я запускаю doctrine orm:schema-tool:create --dump-sql
, таблица Media
дублирует столбцы из Content
. Это результат команды:
CREATE TABLE Content (id INT AUTO_INCREMENT NOT NULL, container_id INT DEFAULT NULL, creationDate DATETIME NOT NULL, publicationDate DATETIME DEFAULT NULL, isGallery TINYINT(1) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB; CREATE TABLE Media (id INT AUTO_INCREMENT NOT NULL, creationDate DATETIME NOT NULL, publicationDate DATETIME DEFAULT NULL, width INT NOT NULL, height INT NOT NULL, isImage TINYINT(1) NOT NULL, bitrate INT NOT NULL, duration INT NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB; CREATE TABLE Gallery (id INT AUTO_INCREMENT NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB; ALTER TABLE Content ADD FOREIGN KEY (container_id) REFERENCES Gallery(id); ALTER TABLE Gallery ADD FOREIGN KEY (id) REFERENCES Content(id) ON DELETE CASCADE
Вот мои классы и аннотации:
content.php
/** @Entity * @InheritanceType("JOINED") * @DiscriminatorColumn(name="isGallery", type="boolean") * @DiscriminatorMap({ * 0 = "Media", * 1 = "Gallery" * }) */ abstract class Content { /** @Id @GeneratedValue @Column(type="integer") */ private $id; /** @Column(type="datetime") */ private $creationDate; /** @Column(type="datetime", nullable="true") */ private $publicationDate; /** @ManyToOne(targetEntity="Gallery", inversedBy="contents") */ private $container; }
Media.php
/** @Entity * @InheritanceType("SINGLE_TABLE") * @DiscriminatorColumn(name="isImage", type="boolean") * @DiscriminatorMap({ * 0 = "Video", * 1 = "Image" * }) */ abstract class Media extends Content { /** @Column(type="integer") */ private $width; /** @Column(type="integer") */ private $height; }
Gallery.php
/** @Entity */ class Gallery extends Content { /** @OneToMany(targetEntity="Content", mappedBy="container") */ private $contents; }
Video.php
/** @Entity */ class Video extends Media { /** @Column(type="integer") */ private $bitrate; /** @Column(type="integer") */ private $duration; }
image.php
/** @Entity */ class Image extends Media { }
Я спрашиваю: это правильное поведение? Должны ли Media
иметь только поля id
, width
и height
, плюс bitrate
и duration
Video
?
Кроме того, есть ли способ избавиться от ненужной таблицы Gallery
?
Надеюсь, я достаточно четко дал понять, что не стесняйтесь спрашивать. Заранее спасибо.
ОБНОВЛЕНИЕ: Ни в коем случае. Я попытался найти еще более простой пример, не демонстрирующий этого поведения, но я не нашел его.
Какие-либо предложения? Может ли это быть ошибкой в Doctrine 2 или я пропустил более простое решение?
Я сам отвечаю на свой вопрос, надеясь, что когда-нибудь это поможет кому-то.
Я открыл отчет об ошибке в github для doctrine2 с этим вопросом, и ответ довольно ясен: это не поддерживается.
ОБНОВЛЕНО 2013/07/27
Я просто пробовал это с Doctrine 2.3.4, и он работает так, как ожидалось. : D
Если они все абстрактны, я считаю, что имеет смысл помещать DiscriminatorMap
только в объект верхнего уровня.