使用OptionsResolver组件进行高级类型验证

yce*_*uto 5 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']);
Run Code Online (Sandbox Code Playgroud)

错误!允许FozBaz实例.


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

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

$resolver = new OptionsResolver();
$resolver->setRequired('data');
$resolver->setAllowedTypes('data', ['Bar']);
Run Code Online (Sandbox Code Playgroud)

错误!也允许Bar实例.


我可以重新设计我的类/接口,但这不是设计问题.那么,用这个组件可以实现吗?

Hea*_*eah 5

请参见定义表单选项允许的值,具体取决于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;
});
Run Code Online (Sandbox Code Playgroud)