如何在Doctrine的类表继承中将descriminator列定义为ENUM?

时间:2018-06-19 17:05:30

标签: mysql inheritance enums doctrine-orm class-table-inheritance

我要实现Class Table Inheritance

/**
 * Foo
 *
 * @ORM\Table(name="foos", ...)
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({
 *     "bar" = "Bar",
 *     "buz" = "Buz"
 * })
 */
abstract class Foo
{
    ...
}

由于我运行的是“代码优先”方法,因此数据库是由Doctrine生成的:

$ bin/console doctrine:migrations:diff
$ bin/console doctrine:migrations:migrate

鉴别符列foos.type的类型为VARCHAR(255)。我希望它得到一个ENUM

如何为实体类定义注释以获取ENUM鉴别符?

2 个答案:

答案 0 :(得分:0)

它与columnDefinition="ENUM('bar', 'buz')"兼容:

/**
 * Foo
 *
 * @ORM\Table(name="foos", ...)
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="type", type="string", columnDefinition="ENUM('bar', 'buz')")
 * @ORM\DiscriminatorMap({
 *     "bar" = "Bar",
 *     "buz" = "Buz"
 * })
 */
abstract class Foo
{
    ...
}

不幸的是,它会引起烦人的副作用(例如here):Doctrine的迁移机制似乎无法正确处理ENUMdoctrine:migrations:diff命令创建如下迁移:

final class Version20180619205625 extends AbstractMigration
{
    public function up(Schema $schema) : void
    {
        $this->addSql('ALTER TABLE foos CHANGE type `type` ENUM(\'bar\', \'buz\')');
    }

    public function down(Schema $schema) : void
    {
        $this->addSql('ALTER TABLE tasks CHANGE `type` type VARCHAR(255) DEFAULT NULL COLLATE utf8mb4_unicode_ci');
    }
}

我执行它,type列变为ENUM。但是doctrine:migrations:diff的新执行再次创建了具有相同内容的迁移...意味着,Doctrine认为,该列仍为VARCHAR

答案 1 :(得分:0)

答案有点晚,但是解决方案是注册一个自定义映射类型,该类型将在数据库端实际使用ENUM。最简单的:

class YourType extends Type
{
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
    {
        return 'ENUM(\'one\', \'two\')';
    }
}

使用某些your_type名称在您的Doctrine配置中注册并使用:

 @ORM\DiscriminatorColumn(name="type", type="your_type")

默认情况下,此字段为非空。如果是mysql,它将使用ENUM中的第一个值作为默认值,例如“隐式默认值”