Расширенная проверка типов с помощью компонента OptionsResolver

Мне нужно разрешить типы, которые реализуют два интерфейса (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 экземпляры тоже.


Я могу перепроектировать свои классы / интерфейсы, но это не проблема дизайна. Итак, возможно ли достичь этого с помощью этого компонента?

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

Другие решения

Подпись OptionsResolver::setAllowedTypes() просто этот:

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

Аргумент $allowedTypes может принимать список строк и используется в качестве логики ИЛИ ЖЕ, так любой боюсь, что это все, что вы можете сделать, боюсь …

Обратите внимание, что для того, чтобы разрешить сложные комбинации, которые вы хотите, вам понадобятся либо дополнительные аргументы, либо другие методы, иначе нет способа узнать, хотите ли вы «любой из этих типов», «все эти типы одновременно», «любой тип, кроме этих» или любую другую комбинацию, которую вы можете себе представить …

Я предполагаю, что они могут предоставить метод, который принимает функцию обратного вызова в качестве второго аргумента, так что вы можете делать любые сумасшедшие проверки, которые вы хотите, но насколько мне известно этого не существует (пока).

1

Наконец, я нашел способ, но я совсем не уверен, что это обычный способ:

//...
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 для этого.

1
По вопросам рекламы [email protected]