Как динамически добавлять разделы в конфигурацию Symfony 2? - программирование
Подтвердить что ты не робот

Как динамически добавлять разделы в конфигурацию Symfony 2?

my_bundle:
    algorithm: blowfish # One of 'md5', 'blowfish', 'sha256', 'sha512'

Эта конфигурация выполняется с помощью этого дерева конфигурации:

// Algorithms and constants to check
$algorithms = array(
    'md5'      => 'CRYPT_MD5',
    'blowfish' => 'CRYPT_BLOWFISH',
    'sha256'   => 'CRYPT_SHA256',
    'sha512'   => 'CRYPT_SHA512',
);

$rootNode
    ->children()
        ->scalarNode('algorithm')
            ->isRequired()
            ->beforeNormalization()
                ->ifString()
                ->then(function($v) { return strtolower($v); })
            ->end()
            ->validate()
                ->ifNotInArray(array_keys($algorithms))
                ->thenInvalid('invalid algorithm.')
            ->end()
            ->validate()
                ->ifTrue(function($v) use($algorithms) {
                    return 1 != @constant($algorithms[$v]);
                })
                ->thenInvalid('algorithm %s is not supported by this system.')
            ->end()
        ->end()
    ->end();

Поскольку для каждого алгоритма требуются разные параметры, как я могу динамически добавлять их в качестве дочерних элементов корня node, основываясь на выбранном алгоритме?

Например, если алгоритм "blowfish", должен быть скаляр node с именем "cost", а если "sha512" - скалярные node "раунды", каждый из которых имеет разные правила проверки.

EDIT: мне действительно нужно выяснить текущий алгоритм (как сделать с $rootNode?), а не вызвать:

$rootNode->append($this->getBlowfishParamsNode());
$rootNode->append($this->getSha256ParamsNode());
$rootNode->append($this->getSha512ParamsNode());

EDIT: возможные конфигурации, которые я хотел бы выполнить:

my_bundle:
    algorithm: blowfish
    cost: 15

Другой:

my_bundle:
    algorithm: sha512
    rounds: 50000

И еще:

my_bundle:
    algorithm: md5
4b9b3361

Ответ 1

Вы можете проверить (используя ifTrue()), если значение algorithm равно md5. Если это так, вы отмените клавиши blowfish, sha256, sha513 в массиве, содержащем необработанные значения конфигурации.

Затем вы можете использовать аналогичную логику, если algorithm - blowfish, sha256 или sha513.


$rootNode->
    ->beforeNormalization()
        //...
        ->ifTrue(function($v) {
            // $v contains the raw configuration values
            return 'md5' === $v['algorithm'];
        })
        ->then(function($v) {
            unset($v['blowfish']);
            unset($v['sha256']);
            unset($v['sha512']);
            return $v;
        })
        ->end()
        // ...do same logic for the others
    ->end();

Вам нужно будет использовать что-то вроде этого:

my_bundle:
    algorithm: blowfish
    md5: #your params
    blowfish: #will be unset if algorithm is md5 for example
    sha256: #will be unset if algorithm is md5 for example
    sha512: #will be unset if algorithm is md5 for example

Как вы упомянули, вы можете добавить все из них:

$rootNode->append($this->getMd5ParamsNode());
$rootNode->append($this->getBlowfishParamsNode());
$rootNode->append($this->getSha256ParamsNode());
$rootNode->append($this->getSha512ParamsNode());

ИЗМЕНИТЬ

Существует также функция thenUnset().

ИЗМЕНИТЬ

Doctrine способ сделать это может представлять интерес здесь.

Ответ 2

Gremo, может быть, im на неправильном треке здесь. Кстати, спасибо за ваш ответ по моему вопросу.

Это просто мнение, может быть, это просто глупый ответ... ну вот мы идем.

Для вашего ответа я знаю, что вы уже знаете/понимаете, как работает расширение пакета.

Возможно, вы можете определить 4 пустых параметра, необходимых, как показано на configuring-services-and-setting-parameters

... вы установите этот параметр в своем классе расширения на основе входящих значений конфигурации...

Затем вы можете иметь определенные проверки на дереве (например, если алгоритм "blowfish", тогда требуется стоимость)

$rootNode->
    ->beforeNormalization()
        ->ifTrue(function($v) {
            // $v contains the raw configuration values
            // if 'algorithm' blowfish -> cost isRequired
            // or as you said on your question you can call
            // ->append($this->addBlowfishParametersNode())
        })
        ->then(function($v) {
            // maybe some unsetting, but not needed
        })
        ->end()
    ->children()
        // ...
    ->end()
;

Отметьте " Добавление разделов"

public function addBlowfishParametersNode()
{
    $builder = new TreeBuilder();
    $node = $builder->root('parameters');

    $node
        ->isRequired()
        ->requiresAtLeastOneElement()
        ...
        ...