Why isn't my custom Symfony validator executed?

1.9k Views Asked by At

I have the following classes

The entity to be validated:

<?php
//CompanyName\DataBundle\Entity\Intern\Address.php

namespace CompanyName\DataBundle\Entity\Intern;

use CompanyName\DataBundle\Entity\Country;

use Swagger\Annotations\Property;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use CompanyName\ConstraintValidatorBundle\ConstraintValidator;
use CompanyName\ConstraintValidatorBundle\Entity\CountryZipCodeAwareInterface;

/**
 * Class Address
 * @package CompanyName\DataBundle\Entity\Intern
 * @ConstraintValidator\ZipCode
 */
class Address implements CountryZipCodeAwareInterface
{
    /**
     * originId for 'API' send to the Addressbridge and stored in the Addresservice
     *
     * 
     * 
     */
    const ORIGIN_ID_FOR_ADDRESS_FROM_API = 2;

    /**
     * @var integer
     */
    private $id;

    /**
     * @var Name
     * @Property(type="string")
     * @Groups({"createOrder", "shoppingCart"})
     * @Assert\NotBlank()
     * @Assert\Valid()
     */
    private $name;

    /**
     * @var string
     * @Groups({"createOrder", "shoppingCart"})
     * @Assert\NotBlank()
     * @Assert\Type("string")
     * @Assert\Length(max = 100, maxMessage = "Street name cannot be longer than {{ limit }} characters")
     */
    private $street;

    /**
     * @var string
     * @Groups({"createOrder", "shoppingCart"})
     * @Assert\NotBlank()
     * @Assert\Type("string")
     * @Assert\Regex("/^\d+$/")
     * @Assert\Length(max = 5, maxMessage = "House number cannot be longer than {{ limit }} characters")
     */
    private $housenumber;

    /**
     * @var string
     * @Groups({"createOrder", "shoppingCart"})
     * @Assert\Type("string")
     * @Assert\Length(max = 25, maxMessage = "Addition cannot be longer than {{ limit }} characters")

    /**
     * @var Country
     * @Property(type="string")
     * @Groups({"createOrder", "shoppingCart"})
     * @Assert\NotBlank()
     * @Assert\Valid()
     */
    private $country;    
}

A constraint to use in my custom validator:

<?php
//CompanyName\DataBundle\Validator\Name.php

namespace CompanyName\DataBundle\Validator;

use Symfony\Component\Validator\Constraint;

/**
 * Class Name
 * @package CompanyName\DataBundle\Validator
 * @Annotation
 */
class Name extends Constraint
{
    public $message = "No Valid Name provided";

    /**
     * {@inheritdoc}
     */
    public function getTargets()
    {
        die("gggggg");
        return self::CLASS_CONSTRAINT;
    }
}

The actual validator:

<?php
//CompanyName\DataBundle\Validator\NameValidator.php

namespace CompanyName\DataBundle\Validator;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class NameValidator extends ConstraintValidator
{
    /**
     * Checks if the passed value is valid.
     *
     * @param Name name The value that should be validated
     * @param Constraint $constraint The constraint for the validation
     */
    public function validate($name, Constraint $constraint)
    {
        var_dump($name);
        die();

    }
}

Assert\Valid() is not working. It throws the following error:

ExceptionListener.php on line 17: Symfony\Component\Validator\Exception\NoSuchMetadataException {#1052
message: "The class or interface "test" does not exist."

The following is the Payload:

 "invoiceAddress": {
    "name": "test",
    "street": "Dorpsstraat",
    "housenumber": "123",
    "zipcode": "1234AB",
    "city": "Dorp",
    "country": "nl"
  },
  "deliveryAddress": {
    "name": "Naam",
    "street": "Dorpsstraat",
    "housenumber": "123",
    "housenumberAddition": "A",
    "zipcode": "1234AB",
    "city": "Dorp",
    "country": "nl"
  },
2

There are 2 best solutions below

5
On BEST ANSWER

You are using the wrong validator.

First import the appropriate namespace into your class definition:

use CompanyName\DataBundle\Validator as CompanyAsserts;

And then your property annotations should look like this:

/**
* @var Name
* @Property(type="string")
* @Groups({"createOrder", "shoppingCart"})
* @Assert\NotBlank()
* @CompanyAsserts\Name
*/
private $name;

This way you are actually using your custom validator. Remove @Assert\Valid(), that's not the validatior you are looking for.

You'll also need to update your constraint annotations:

/**
 * Class Name
 * @package CompanyName\DataBundle\Validator
 * @Annotation
 * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
 */
class Name extends Constraint {
   // your class
}

(Note the @Target annotation). Also, remove the getTargets() method from this class.

0
On

You have to use your custom validator assertion. @Assert\Valid() annotation should be used when you want to validate property that has relation to your entity (e.g when you have User to Address relation and you want to have some custom validation on $address at User entity).

That's why it looks for class test to validate. Look in to the documentation here