Multiple discrimination levels while using Doctrin

2019-04-30 19:25发布

I'm using Doctrine2 to manage my model below: There's an abstract concept Content with a Composite pattern in Gallery, also an abstract concept Media from which Video and Image inherits.

My choice was to add discriminators to Content and Media tables in order to differentiate between Gallery, Video and Image. Content uses JOIN inheritance and Media uses SINGLE_TABLE inheritance.

As I run doctrine orm:schema-tool:create --dump-sql, Media table is duplicating columns from the Content one. That's the output of the command:

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

Here are my classes and annotations:

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
{
}

I ask: That's the correct behaviour? Should not Media have only the fields id, width and height, plus bitrate and duration from Video?

Besides, is there a way to get rid of the unnecesary Gallery table?

I hope I made it clear enough, though, feel free to ask. Thank you in advance.

UPDATE: No way. I tried to find an even simpler example not showing this behavior, but I found none.

Any suggestions? Could this be a bug in Doctrine 2 or I'm missing a simpler solution?

2条回答
男人必须洒脱
2楼-- · 2019-04-30 19:36

If they're all abstract I find it makes more sense to put DiscriminatorMap only in the top level entity.

查看更多
beautiful°
3楼-- · 2019-04-30 19:46

I answer my question myself hoping it will help someone someday.

I opened a bug report in github for doctrine2 with this question and the answer is pretty clear: This is not supported.

UPDATED 2013/07/27

I just tried this with Doctrine 2.3.4 and it works as expected. :D

查看更多
登录 后发表回答