Yonel Yonel - 2 months ago 8
PHP Question

Advanced type validation with OptionsResolver component

I need allow types that implement two interfaces (

Foo
and
Bar
), not one of them.

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


Wrong! allows
Foz
and
Baz
instances too.




I need allow types subclass of
Bar
, not
Bar
instances.

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

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


Wrong! allows
Bar
instances too.




I can redesign my classes/interfaces but it's not a design problem. So, is possible reach it with this component?

Answer

See Define a form option allowed values depending on another option value in a FormType.

You should use a normalizer for this:

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;
});
Comments