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

时间:2016-06-27 21:09:21

标签: symfony orm doctrine-orm mapping yaml

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

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

fields:
    name:
        type: string
        localizable: true

然后,我想通过

获取有关此可本地化属性的信息
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
            }
        }
    }

2 个答案:

答案 0 :(得分:3)

写作学说的方式使得这很尴尬。您似乎想要保留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;
            }
        }
    }
}

然后我告诉Symfony通过覆盖app/config/parameters.yml内的类来使用此驱动程序

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

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

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

会给我:

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

答案 1 :(得分:0)

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

在你的情况下,我看到的最简单的方法是添加一个自定义类型,让我们说LocalizableText(我想最多你需要那个,也许$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 } } } )。 添加类型相对简单,因为您可以扩展基类型,因此您不必编写任何SQL。您可以参考Doctrine文档here和Doctrine捆绑一个here

然后你可以这样做:

df.groupby('Column A')['Column B'].agg(lambda x: list(x)).to_dict()
Out[42]: 
{'ID1': ['ID5', 'ID6', 'ID7'],
 'ID2': ['ID8', 'ID9'],
 'ID3': ['ID8', 'ID9', 'ID10', 'ID11']}