feycot
@feycot

Как с помощью Sypfony Validation 3.4 проверить ключ на тип массиву + его элементы, но не проверять элементы если не массив?

Добрый день, есть набор ассертов для проверки входящих параметров (массива)
$rules = new Assert\Collection([
        'userdata' => new Assert\Required([new Assert\Collection([
            'fullname'  => new Assert\NotBlank(),
            'email'     => new Assert\Email(),
            'telephone' => new Assert\NotBlank(),
            ])
        ]),
        "items"    => new Assert\Required([
            new Assert\Type('array'),
            new Assert\NotBlank(),
            new Assert\All([
                new Assert\Type('array'),
                new Assert\Collection([
                    "id"        => new Assert\NotBlank(),
                    "quantity"  => new Assert\NotBlank(),
                    ])
                ])
            ]),
    ]);


Как проверить ключ items на тип массива, и если это массив, то и его элементы?
Если items не массив, то отдать ошибку и не проверять дальше дочерние элементы, если массив, то проверить атрибуты дочерних элементов
В данный момент, если я передаю целое число в ключе items, то выдается ошибка "Expected argument of type \"array or Traversable and ArrayAccess\", \"string\" given"
  • Вопрос задан
  • 193 просмотра
Решения вопроса 1
BoShurik
@BoShurik Куратор тега Symfony
Symfony developer
Судя по всему это "баг"версии 3.4: https://github.com/symfony/symfony/issues/26463
Вот PR, который решает проблему, но он замерджен в 4.2: https://github.com/symfony/symfony/pull/27917

В качестве решения:
$rules = new Assert\Collection([
    "items"    => new Assert\Required([
        new Assert\NotBlank(),
        new Assert\Callback(function ($value, ExecutionContextInterface $context) {
            $validator = $context->getValidator();

            $violations = $validator->validate($value, new Assert\Type('array'));

            if ($violations->count() > 0) {
                /** @var ConstraintViolationInterface $violation */
                foreach ($violations as $violation) {
                    $context
                        ->buildViolation($violation->getMessage(), $violation->getParameters())
                        ->atPath('items')
                        ->addViolation()
                    ;
                }

                return;
            }

            $violations = $validator->validate($value, new Assert\All([
                new Assert\Type('array'),
                new Assert\Collection([
                    "id"        => new Assert\NotBlank(),
                    "quantity"  => new Assert\NotBlank(),
                ])
            ]));

            /** @var ConstraintViolationInterface $violation */
            foreach ($violations as $violation) {
                $context
                    ->buildViolation($violation->getMessage(), $violation->getParameters())
                    ->atPath('items'. $violation->getPropertyPath())
                    ->addViolation()
                ;
            }
        }),
    ]),
]);

$validator = Validation::createValidator();

$data = [
    'items' => [
        [
            'id' => 'id',
            'quantity' => 'quantity',
        ],
    ],
];

dump($validator->validate($data, $rules)); // Ok

$data = [
    'items' => 1,
];

dump($validator->validate($data, $rules)); // Ko

$data = [
    'items' => [
        [
            'id' => 'id',
            'quantity' => 'quantity',
        ],
        [
            'id2' => 'id',
            'quantity2' => 'quantity',
        ]
    ],
];

dump($validator->validate($data, $rules)); // Ko
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы