Skip to content

[Validator] type constraint with multi-types is not handled #31330

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lofk opened this issue Apr 30, 2019 · 2 comments
Closed

[Validator] type constraint with multi-types is not handled #31330

lofk opened this issue Apr 30, 2019 · 2 comments

Comments

@lofk
Copy link

lofk commented Apr 30, 2019

Symfony version(s) affected: 4.2.1

Description
When I define a constraint type with multi-types (array of types), PHP returns a warning on line : symfony/validator/Constraints/TypeValidator.php:36, (strtolower() function with an array).

How to reproduce
Create an object with a property having the following type constraint :

    /**
     * @var string|array
     * @Assert\Type(type={"string", "array"})
     */
    private $name;

Possible Solution

  • option 1 : throws a InvalidMultiTypesException
  • option 2 : handle the multi-types constraint, by looping on the optional types, and validate if one of them is valid.

Additional context

"message":"{"type":"api_exception","code":0,"message":"Warning: strtolower() expects parameter 1 to be string, array given","stack_trace":"#0 /var/www/html/vendor/symfony/validator/Validator/RecursiveContextualValidator.php(804): Symfony\Component\Validator\Constraints\TypeValidator->validate('2', Object(Symfony\Component\Validator\Constraints\Type))
@ro0NL
Copy link
Contributor

ro0NL commented Apr 30, 2019

That be a new feature, it's documented to be a string currently: https://symfony.com/doc/current/reference/constraints/Type.html#reference-constraint-type-type

@fabpot fabpot closed this as completed Jun 4, 2019
fabpot added a commit that referenced this issue Jun 4, 2019
…ypes (jschaedl)

This PR was merged into the 4.4 branch.

Discussion
----------

[Validator] Improve TypeValidator to handle array of types

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #31330
| License       | MIT
| Doc PR        | tbd.

The `@Type` constraint is now able to handle multiple types:

```php
/**
 * @var string|array
 * @Assert\Type(type={"string", "array"})
 */
 private $name;
```

and will pass when `$name` is either of type `string` or `array`.

Commits
-------

c8100f3 [Validator] Improve TypeValidator to handle array of types
@theoarena
Copy link

For those who are using an old validator version and cannot upgrade it, you can use Assert\CallBack to simulate "multiple types" (or whatever you need).

For example, if you want to validate your data as new Assert\Type('numeric') and new Assert\Type('array') simultaneously:


public function assertIsArray($object, ExecutionContextInterface $context, $payload){

      if( !is_array($object) )
          throw new \Exception( "Field '". $context->getPropertyPath() . "': should be of type array", 400 );

      $errors = $this->validator->validate($object, $payload);

      if (count($errors) > 0)
          throw new \Exception( "Field '". $context->getPropertyPath() . "': ". $errors->get(0)->getMessage(), 400 );

  }

//Now declare your constraint

$constraint = new Assert\Callback([
    'callback' => [$this, 'assertIsArray'], 
    'payload' => new Assert\Type('numeric')
]);

You could even have 'payload' as an array and iterate over it to apply your validations one at a time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants