我需要允许类型实现两个接口(Foo
和Bar
),而不是其中之一。
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']);
错误!也允许Foz
和Baz
个实例。
我需要允许Bar
的类型子类,而不是Bar
个实例。
class Bar {};
class Foobar extends Bar {};
class FoobarBaz extends Foobar {};
$resolver = new OptionsResolver();
$resolver->setRequired('data');
$resolver->setAllowedTypes('data', ['Bar']);
错误!也允许Bar
个实例。
我可以重新设计我的类/接口,但这不是设计问题。 那么,是否可以使用此组件实现它?
答案 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');
//...
修改强>
好吧,在我睡觉之后,我认为我的方法是错误的,因为它已经通过使用setAllowedValues
或addAllowedValues
方法完成了:
$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 不存在(还)。