如何将自定义 属性 添加到 Symfony Doctrine YAML 映射文件

How to add custom property to Symfony Doctrine YAML mapping file

谁能告诉我如何将自定义 属性 添加到 doctrine ORM yml 文件中?

我的想法是像这样添加一个属性:

fields:
    name:
        type: string
        localizable: true

然后我想通过使用

获取关于这个localizable属性的信息
protected function getEntityMetadata($entity)
{
    $factory = new DisconnectedMetadataFactory($this->getContainer()->get('doctrine'));

    return $factory->getClassMetadata($entity)->getMetadata();
}

然后:

    $met    = $this->getEntityMetadata($bundle.'\Entity\'.$entity);
    $this->metadata = $met[0];
    $fields = $this->metadata->fieldMappings;

    if (isset($fields)) {

        foreach ($fields as $field => $fieldMapping) {
            if (isset($fieldMapping['localizable']) && $fieldMapping['localizable'] == true) {

                // Do sth with it
            }
        }
    }

不幸的是,如果不重写 Doctrine DBAL 的重要部分,这是不可能的。这会影响驱动程序(YAML、注释...)、元数据生成器...

在您的情况下,我认为最简单的方法是添加一个自定义类型,比方说 LocalizableString(我猜您至多需要它,也许 LocalizableText)。 添加类型相对简单,因为您可以扩展基类型,因此不必编写任何 SQL。可以参考 Doctrine 文档 here and Doctrine bundle one here.

那么你可以这样做:

$met    = $this->getEntityMetadata($bundle.'\Entity\'.$entity);
$this->metadata = $met[0];
$fields = $this->metadata->fieldMappings;

if (isset($fields)) {

    foreach ($fields as $field => $fieldMapping) {
        if ($this->getClassMetadata()->getTypeOfField($field) === 'localized_string') {

            // Do sth with it
        }
    }
}

学说的书写方式让这变得很尴尬。您似乎想保留 Yaml 映射,但只添加一个 属性。我认为您可以从提供的驱动程序扩展创建自己的自定义驱动程序。 Yaml 驱动程序主要有私有方法,因此很难覆盖一些功能,但这是可能的。

我创建了一个扩展自 SimplifiedYamlDriver 的自定义驱动程序。驱动程序的命名很重要,因为学说扩展将尝试根据 Driver 之前的内容加载其驱动程序之一。它还会对名称中的 Simplified 进行 strpos 检查,所以我认为最安全的做法是完全保留原始名称并给原始名称起一个别名。

use Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver as BaseDriver;

class SimplifiedYamlDriver extends BaseDriver
{
    public function loadMetadataForClass($className, ClassMetadata $metadata)
    {
        parent::loadMetadataForClass($className, $metadata);

        $element = $this->getElement($className);

        if (!isset($element['fields'])) {
            return;
        }

        foreach ($element['fields'] as $name => $fieldMapping) {
            if (isset($fieldMapping['localizable'])) {
                $original = $metadata->getFieldMapping($name);
                $additional = ['localizable' => $fieldMapping['localizable']];
                $newMapping = array_merge($original, $additional);
                $metadata->fieldMappings[$newMapping['fieldName']] = $newMapping;
            }
        }
    }
}

然后我通过覆盖 app/config/parameters.yml

中的 class 告诉 Symfony 使用这个驱动程序
parameters:
    doctrine.orm.metadata.yml.class: MyBundle\SimplifiedYamlDriver

然后我更新了映射,就像您在 MyBundle/Resources/config/doctrine/Foo.orm.yml

中的示例一样
MyBundle\Entity\Foo:
    type: entity
    id:
        id:
            type: integer
            generator:
                strategy: IDENTITY
    fields:
        text:
            type: string
            localizable: true

我可以在任何可以访问学说的地方获取此映射:

$mapping = $this
            ->getDoctrine()
            ->getEntityManager()
            ->getClassMetadata(Foo::class)
            ->getFieldMapping('text');

会给我:

Array
(
    [fieldName] => text
    [type] => string
    [columnName] => text
    [localizable] => 1
)