如何将Symfony配置树绑定到对象

如何将Symfony配置树绑定到对象,symfony,Symfony,如何将Symfony配置树绑定到类而不是返回数组 使用Symfony\Component\Config\Definition\Processor返回一个数组 在我的例子中,我希望将配置绑定到一个类,这样我就可以使用方法来组合部分数据 下面是我的用例的一个简单示例。我希望将配置绑定到一个类,这样我就可以使用一个方法将table.name和table.version连接在一起(我的实际用例更复杂,但这是一个简单的示例) config.yml db: table: name:

如何将Symfony配置树绑定到类而不是返回数组

使用
Symfony\Component\Config\Definition\Processor
返回一个数组

在我的例子中,我希望将配置绑定到一个类,这样我就可以使用方法来组合部分数据

下面是我的用例的一个简单示例。我希望将配置绑定到一个类,这样我就可以使用一个方法将table.name和table.version连接在一起(我的实际用例更复杂,但这是一个简单的示例)

config.yml

  db:
    table:
      name: some_table
      version: v2
配置界面

class DBConfiguration implements ConfigurationInterface
{
    /**
     * {@inheritDoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('db');

        $rootNode
            ->children()
                ->arrayNode('table')
                    ->children()
                        ->scalarNode('name')->isRequired()->end()
                        ->scalarNode('version')->end()
                    ->end()
                ->end()
        ;

        return $treeBuilder;
    }
}
我要将配置绑定到的类

class DB
{

    public $table;

    public function __construct()
    {
        $this->table = new Table();
    }

}


class Table
{

    public $name;
    public $version;

    /**
     * @return string
     * Calculate the full table name.
     */
    public function getTableName()
    {
        return $this->name.'-'.$this->version;
    }

}

据我所知,Symfony没有本机支持,但是,您可以自己实现它。您可以使用的子集负责反序列化,但我认为这样做太过分了。特别是因为我没有看到任何
publicpropertydennormalizer
,只有
GetSetMethodNormalizer
(它也是反规范化程序)。因此,您必须让您的配置对象具有
get/set
方法,或者自己滚动
PublicPropertyDenormalizer
。这是可能的,但看起来确实有些过火,也没有多大帮助:

Symfony序列化程序组件 原生PHP方式 在我看来,这比上面简单多了,因为Symfony Serializer并没有真正做到这一点

$array = [
    'field1' => 'F1',
    'subobject' => [
        'subfield1' => 'SF1',
    ],
];

trait Denormalizable
{
    public function fromArray($array)
    {
        foreach ($array as $property => $value) {
            if (is_array($value)) {
                if ($this->$property instanceof ArrayDenormalizableInterface) {
                    $this->$property->fromArray($value);    
                } else {
                    $this->$property = $value;
                }
            } else {
                $this->$property = $value;
            }
        }
    }
}

interface ArrayDenormalizableInterface
{
    public function fromArray($array);
}

class MyConfigObject implements ArrayDenormalizableInterface
{
    use Denormalizable;

    public $field1;

    public $subobject;

    public function __construct()
    {
        $this->subobject = new SubObject();
    }
}

class SubObject implements ArrayDenormalizableInterface
{
    use Denormalizable;

    public $subfield1;
}

$myConf = new MyConfigObject();
$myConf->fromArray($array);

无论您选择何种方式,现在都可以将从symfony processor返回的数组转换为所需的配置对象。

symfony配置组件不支持这一点

然而,在Symfony项目中,这通常是在同一时间完成的。在bundle的
扩展
类中,您将可以以数组形式访问bundle的配置树

然后,您可以获取该数组并将其分配给服务容器中定义的服务,该服务容器将创建您的配置对象

这正是
DoctrineBundle
的配置类的构建方式:

  • $array = [
        'field1' => 'F1',
        'subobject' => [
            'subfield1' => 'SF1',
        ],
    ];
    
    trait Denormalizable
    {
        public function fromArray($array)
        {
            foreach ($array as $property => $value) {
                if (is_array($value)) {
                    if ($this->$property instanceof ArrayDenormalizableInterface) {
                        $this->$property->fromArray($value);    
                    } else {
                        $this->$property = $value;
                    }
                } else {
                    $this->$property = $value;
                }
            }
        }
    }
    
    interface ArrayDenormalizableInterface
    {
        public function fromArray($array);
    }
    
    class MyConfigObject implements ArrayDenormalizableInterface
    {
        use Denormalizable;
    
        public $field1;
    
        public $subobject;
    
        public function __construct()
        {
            $this->subobject = new SubObject();
        }
    }
    
    class SubObject implements ArrayDenormalizableInterface
    {
        use Denormalizable;
    
        public $subfield1;
    }
    
    $myConf = new MyConfigObject();
    $myConf->fromArray($array);