Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 it possible achieve it with this component?

like image 960
yceruto Avatar asked Sep 28 '16 15:09

yceruto


2 Answers

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;
});
like image 190
Heah Avatar answered Nov 20 '22 19:11

Heah


Finally, I found a way but I'm not sure at all that it's a conventional way:

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

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

EDIT:

Well, after I sleep on, I think my approach is wrong, because it's already done by using setAllowedValues or addAllowedValues methods:

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

So it's not necessary to use setAllowedTypes for this purpose.

like image 2
yceruto Avatar answered Nov 20 '22 19:11

yceruto