使用OptionsResolver组件

时间:2016-09-28 15:20:21

标签: php symfony symfony-components options-resolver

我需要允许类型实现两个接口(FooBar),而不是其中之一。

interface Foo {};
interface Bar {};

class Foz implements Foo {};
class Baz implements Bar {};
class Foobar implements Foo, Bar {};

$resolver = new OptionsResolver();
$resolver->setRequired('data');
$resolver->setAllowedTypes('data', ['Foo', 'Bar']);

错误!也允许FozBaz个实例。

我需要允许Bar的类型子类,而不是Bar个实例。

class Bar {};
class Foobar extends Bar {};
class FoobarBaz extends Foobar {};

$resolver = new OptionsResolver();
$resolver->setRequired('data');
$resolver->setAllowedTypes('data', ['Bar']);

错误!也允许Bar个实例。

我可以重新设计我的类/接口,但这不是设计问题。 那么,是否可以使用此组件实现它?

3 个答案:

答案 0 :(得分:5)

请参阅Define a form option allowed values depending on another option value in a FormType

您应该使用规范化程序

use Symfony\Component\Form\Exception\InvalidConfigurationException;

$resolver->setNormalizer('data', function(Options $options, $data) {
    if (!$data instanceof Foo && !$data instanceof Bar) {
        throw new InvalidConfigurationException('"data" option must implement "Foo" and "Bar" interfaces.');
    }

    return $data;
});

答案 1 :(得分:2)

最后,我找到了一种方法,但我完全不确定这是一种传统方式:

//...
function is_foobar($value) {
    //return true or false;
}

$resolver = new OptionsResolver();
$resolver->setRequired('data');
$resolver->setAllowedTypes('data', 'foobar');
//...

修改

好吧,在我睡觉之后,我认为我的方法是错误的,因为它已经通过使用setAllowedValuesaddAllowedValues方法完成了:

$resolver->setAllowedValues('foo', function ($value) {
    return $value instanceof Foo && $value instanceof Bar;
});

因此,没有必要为此目的使用setAllowedTypes

答案 2 :(得分:1)

OptionsResolver::setAllowedTypes()的签名只是this

setAllowedTypes(string $option, string|string[] $allowedTypes)

参数$allowedTypes可以接受字符串列表,并用作逻辑 OR ,因此任何这些类型都将被允许 - 这就是全部你可以做我害怕......

请注意,为了允许您想要的复杂组合,您需要更多参数或其他方法,否则无法知道您是否需要“任何这些类型”,“所有这些类型都在同一个时间“,”任何类型,但这些“或你能想象的任何其他组合......

我猜他们可能会提供一个接受回调函数作为第二个参数的方法,所以你可以做任何你想要的疯狂检查,但 AFAIK 不存在(还)。