在 Doctrine 中映射 class 名称

Mapping class name in Doctrine

我正在构建一个应用程序,其中包含一个名为 Element 的对象。 class由2个字段组成(其实还有很多,其他的无关紧要):

简化的class图表:

我很少有 classes 实现 ElementType 接口:

class Type1 implements ElementType {/*...*/}
class Type2 implements ElementType {/*...*/}
class Type3 implements ElementType {/*...*/}

我的元素数据库table也很简单,只有2个相关字段(其余部分从屏幕截图中删除):

问题来了。我不知道如何映射 class (Type1, Type2...) 并将其保存为 elements table 中的字符串 (type1, type2...) (如普通嵌入元素)。我搜索了文档,没有找到任何有用的东西。 我当前的映射文件如下所示:

<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                   https://raw.github.com/doctrine/doctrine2/master/doctrine-mapping.xsd">
    <entity name="App\Domain\Element" table="elements" repository-class="App\Repository\ElementRepository">
        <embedded name="id" class="App\Domain\ElementId" use-column-prefix="false" />
        <!--Missing mapping here-->
    </entity>
</doctrine-mapping>

我终于明白了。也许我的解决方案对某人有帮助。该解决方案基于 custom mapping type.

<?php

namespace App\Mapping;

use App\Domain\ElementType;
use App\Domain\Type1;
use App\Domain\TypeFactory;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;

class ElementType extends Type
{
    const NAME = 'element_type';

    public function getSQLDeclaration(array $column, AbstractPlatform $platform)
    {
        return $platform->getVarcharTypeDeclarationSQL($column);
    }

    public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        return TypeFactory::getTypeByString($value);
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform)
    {
        if (!$value instanceof ElementType) {
            throw new \Exception('Wrong type');
        }

        return TypeFactory::getStringByType($value);
    }

    public function getName(): string
    {
        return self::NAME;
    }
}

TypeFactory只是一个简单的switch语句,这里就不贴了。

# config/packages/doctrine.yml
doctrine:
    dbal:
        types:
            element_type:  App\Mapping\ElementType

创建自定义映射类型后,我所要做的就是在我的映射器中实现它:

<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                   https://raw.github.com/doctrine/doctrine2/master/doctrine-mapping.xsd">
    <entity name="App\Domain\Element" table="elements" repository-class="App\Repository\ElementRepository">
        <embedded name="id" class="App\Domain\ElementId" use-column-prefix="false" />
        <field name="type" type="element_type" />
    </entity>
</doctrine-mapping>