如何使用OptionsResolver组件规范化两个相关选项

时间:2016-10-11 14:47:14

标签: php symfony symfony-components options-resolver

我的基于OptionsResolver Component的以下情况:

  • 我有两个选项:barfoo,默认情况下均为null
  • bar选项也接受B值。
  • foo选项也接受ABCD值。

现在,当这些选项得到解决后,如果foo选项等于Abar选项必须更改为B,但我也需要:if { {1}}选项等于fooA,必须将其更改为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),因此对于此测试始终检查{{ 1}}和$options->offsetGet('foo')选项未成功规范化。

如何运作?

2 个答案:

答案 0 :(得分:0)

IMO使用这种方法是不可靠的。你将永远不得不依赖于规范化的顺序,而且很容易迷失。

我宁愿使用第三个选项baz,它不会被更改,就像barfoo的源数据一样。

$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'));

答案 1 :(得分: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'));