Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate if an element of an array is an array itself?

Given this input:

[
    'key' => 'value',
]

How to validate to ensure that:

  1. key attribute exists
  2. Its value is an array (with any number of elements)

I expected this constraint to work

    $constraint = new Collection([
        'key' => new Required([
            new Type('array'),
            new Collection([
                'value' => new Required([
                    new NotBlank(),
                ]),
            ]),
        ]),
    ]);

but it throws an exception:

Symfony\Component\Validator\Exception\UnexpectedTypeException: Expected argument  of type "array or Traversable and ArrayAccess", "string" given

What am I missing?

PS: it's symfony v2.7.1

PPS: just to clarify: I know one can use a callback. If I wanted to re-implement the validation manually from scratch - I wouldn't have used symfony at the very first place. So the question is particularly about combining the existing constraints and not about using a callback constraint..

like image 807
zerkms Avatar asked Jun 24 '15 05:06

zerkms


1 Answers

I had the exact same problem two nights ago.

The conclusion at the very end was that Symfony2 validation has no "fast-fail" validation. That is, even if your Type() constraint would fail it would proceed with other constraints and thus fail with UnexpectedTypeException exception.

However, I was able to find a way to tackle that:

$constraint = new Collection([
    'key' => new Required([
        new Type(['type' => 'array']),
        new Collection([
            // Need to wrap fields into this
            // in order to provide "groups"
            'fields' => [ 
                'value' => new Required([
                    new NotBlank(),
                ]),
            ],
            'groups' => 'phase2' // <-- THIS IS CRITICAL
        ]),
    ]),
]);

// In your controller, service, etc...
$V = $this->get('validator');

// Checks everything by `Collection` marked with special group
$violations = $V->validate($data, $constraint);

if ( $violations->count()){
    // Do something
}

// Checks *only* "phase2" group constraints
$violations = $V->validate($data, $constraint, 'phase2');

if ( $violations->count()){
    // Do something
}

Hope that this helps a bit. Personally, I find it annoying that we need to do this. Some sort of "fast-fail" flag within validator service would be much helpful.

like image 60
Jovan Perovic Avatar answered Sep 28 '22 05:09

Jovan Perovic