Как нормализовать два связанных параметра с помощью компонента OptionsResolver

У меня следующая ситуация, основанная на Компоненты OptionsResolver:

  • У меня есть два варианта: bar а также foo, и то и другое null по умолчанию.
  • bar вариант принимает B значение также.
  • foo вариант принимает A, B, C, D значения также.

Теперь, когда эти параметры разрешены, если foo опция равна A, bar опция должна быть изменена на Bно мне тоже нужно: если foo опция равна A или же B это должно быть изменено на C,


Я пытался реализовать это, но ожидаемый результат неверен:

use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

$resolver = new OptionsResolver();
$resolver->setDefaults(array(
'bar' => null,
'foo' => null,
));
$resolver->setAllowedValues('bar', array(null, 'B'));
$resolver->setAllowedValues('foo', array(null, 'A', 'B', 'C', 'D'));

$resolver->setNormalizer('bar', function (Options $options, $value) {
if ('A' === $options['foo']) {
return 'B';
}

return $value;
});

$resolver->setNormalizer('foo', function (Options $options, $value) {
if ('A' === $value || 'B' === $value) {
$value = 'C';
}

return $value;
});

$options = $resolver->resolve(array('foo' => 'A'));

var_dump($options);

это всегда возвращает:

array(2) {
["foo"] => string(1) "C"["bar"] => NULL  // wrong normalization, expected `B` value.
}

Проблема в том, что 'A' === $options['foo'] заявление в bar нормализатор звонки foo нормализатор (т.е. $options->offsetGet('foo')), прежде чем выполнить условие, поэтому для этого теста всегда проверяет 'A' === 'C' а также bar опция не нормализована успешно.

Как это работает?

0

Решение

ИМО это ненадежно использовать этот подход. Вам всегда придется полагаться на порядок нормализации, и очень легко заблудиться.

Я предпочел бы использовать третий вариант baz который не будет изменен и будет как исходные данные для bar а также foo,

$resolver = new OptionsResolver();
$resolver->setDefaults(array(
'bar' => null,
'foo' => null,
'baz' => null,
));
$resolver->setAllowedValues('bar', array(null, 'B'));
$resolver->setAllowedValues('foo', array(null, 'A', 'B', 'C', 'D'));
$resolver->setAllowedValues('baz', array(null, 'A', 'B', 'C', 'D'));

$resolver->setNormalizer('bar', function (Options $options, $value) {
if ('A' === $options['baz']) {
return 'B';
}

return $value;
});

$resolver->setNormalizer('foo', function (Options $options, $value) {
if ('A' === $options['baz'] || 'B' === $options['baz']) {
$value = 'C';
} else {
return $options['baz'];
}
});

$options = $resolver->resolve(array('baz' => 'A'));
0

Другие решения

Ну, это ужасный обходной путь, но это код, который я наконец-то реализовал:

$resolver = new OptionsResolver();
$resolver->setDefaults(array(
'foo' => null,  // <-- move to top to make sure to normalize first that bar
'bar' => null,  // for internal use
));
$resolver->setAllowedValues('bar', array(null, 'B'));
$resolver->setAllowedValues('foo', array(null, 'A', 'B', 'C', 'D'));

$bar = null;

$resolver->setNormalizer('foo', function (Options $options, $value) use (&$bar) {
if ('A' === $value) {
$bar = 'B';
}

if ('A' === $value || 'B' === $value) {
$value = 'C';
}

return $value;
});

$resolver->setNormalizer('bar', function (Options $options, $value) use (&$bar) {
return $bar;
});

$options = $resolver->resolve(array('foo' => 'A'));
0

По вопросам рекламы [email protected]