Validation


Validation (Validation) is an extremely common task in Web programs. Data entered in the form requires validation. Data also needs to be validated when written to a database or transferred to a web service.

Symfony comes with a Validator component, which makes the verification work simple and transparent. This component is based on JSR303 Bean verification specification.

Basics of verification

The best way to understand verification is to see its practical application. Before we begin, let's assume you create a native PHP object that is used somewhere your program needs:

// src/AppBundle/Entity/Author.phpnamespace AppBundle\Entity; class Author{
    public $name;}

So far, this is just a normal class that serves some purpose for your program. The purpose of verification is to tell you whether the data in the object is valid. To do this, you need to configure a list of rules (called constraints/constraints) that the object must follow in order to be valid. These rules can be specified in a number of different formats (YAML, XML, annotations or PHP).

For example, to ensure that the attribute $name is not empty, add the following:

PHP:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints\NotBlank; class Author{
    public $name;     public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('name', new NotBlank());
    }}
XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8" ?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">     <class name="AppBundle\Entity\Author">
        <property name="name">
            <constraint name="NotBlank" />
        </property>
    </class></constraint-mapping>
YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Author:
    properties:
        name:
            - NotBlank: ~
Annotations:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Constraints as Assert; class Author{
    /**
     * @Assert\NotBlank()
     */
    public $name;}

Protected and private attributes and "getter" methods can also be verified (see Constrained delivery scope).

Use verification service

Next, to actually verify the Author object, use validator The validate method of the service (Validator class). validator The job is simple: read the constraint rules of a class to verify whether the object data satisfies these constraints. If validation fails, a non-empty error list (class ConstraintViolationList) will be returned. Implement this simple example in a controller:

// ...use Symfony\Component\HttpFoundation\Response;use AppBundle\Entity\Author; // ...public function authorAction(){
    $author = new Author();     // ... do something to the $author object
    // ... 对 $author 对象做一些事     $validator = $this->get('validator');
    $errors = $validator->validate($author);     if (count($errors) > 0) {
        /*
         * Uses a __toString method on the $errors variable which is a
         * ConstraintViolationList object. This gives us a nice string
         * for debugging.
         * 对 $errors 变量,即 ConstraintViolationList 对象,使用 __toString 方法。
         * 这给了我们一个美观的字符串用于调试。
         */
        $errorsString = (string) $errors;         return new Response($errorsString);
    }     return new Response('The author is valid! Yes!');}

If the $name property is empty, you will see an error message:

If you insert a value for the name attribute, a pleasant success message will appear.

Most of the time, you don't need to interact directly with the validator service, or worry about outputting error messages. In most cases, you use validation indirectly when processing submitted form data. See Validation and Forms to learn more.

You can also pass a "collection of errors" to the template:

if (count($errors) > 0) {
    return $this->render('author/validation.html.twig', array(
        'errors' => $errors,
    ));}

In the template, you can output the exact error list as needed:

PHP:<!-- app/Resources/views/author/validation.html.php -->
<h3>The author has the following errors</h3>
<ul><?php foreach ($errors as $error): ?>
    <li><?php echo $error->getMessage() ?></li><?php endforeach ?></ul>
Twig:{# app/Resources/views/author/validation.html.twig #}<h3>The author has the following errors</h3>
<ul>{% for error in errors %}
    <li>{{ error.message }}</li>{% endfor %}</ul>


Every validation error (called a "constraint violation/constraint violation") is caused by A ConstraintViolation object to render.

Configuration

#Symfony’s validator is enabled by default, but if you use annotation to specify constraints, you must explicitly enable it ( used for verification) annotation:

PHP:// app/config/config.php$container->loadFromExtension('framework', array(
    'validation' => array(
        'enable_annotations' => true,
    ),));
XML:<!-- app/config/config.xml --><?xml version="1.0" encoding="UTF-8" ?><container xmlns="http://symfony.com/schema/dic/services"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:framework="http://symfony.com/schema/dic/symfony"    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd        http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">     <framework:config>
       <framework:validation enable-annotations="true" />    </framework:config></container>
YAML:# app/config/config.ymlframework:
    validation: { enable_annotations: true }


Constraint Rules

Validator is designed to validate objects against constraints (i.e. rules). To validate an object, simply map one or more constraints to the class it is validating and then pass it to the validator service.

Behind the scenes, a constraint is a PHP object that generates a statement for decision making. In practice, a constraint could be "the cake must not burn". In Symfony, constraints are similar: they are assertions about whether a condition is true. Given a value, the constraint tells you whether the value obeys your constraint rules.

Supported constraints

Symfony encapsulates many of the most commonly used constraints:

Basic constraints

These are basic constraints: use them to assert very basic things about property values, or to assert the return values ​​of methods in your program.

Range

##EqualTo

Date

##Collection Constraints

File

Bic

Callback

    ##Expression
  • All
  • UserPassword
  • ##Valid
  • You can also create your own custom constraints. How to create custom validation constraints
  • This article covers this topic.
  • Configuration of constraints

    Some constraints, like NotBlank are relatively simple, while others, like Choice constraints, have many Available configuration options. Assume that the Author class has another attribute called gender, which can be set to "male", "female" or "other":

    PHP:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints as Assert; class Author{
        public $gender;     // ...     public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            // ...         $metadata->addPropertyConstraint('gender', new Assert\Choice(array(
                'choices' => array('male', 'female', 'other'),
                'message' => 'Choose a valid gender.',
            )));
        }}
    XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8" ?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">     <class name="AppBundle\Entity\Author">
            <property name="gender">
                <constraint name="Choice">
                    <option name="choices">
                        <value>male</value>
                        <value>female</value>
                        <value>other</value>
                    </option>
                    <option name="message">Choose a valid gender.</option>
                </constraint>
            </property>         <!-- ... -->
        </class></constraint-mapping>
    YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Author:
        properties:
            gender:
                - Choice: { choices: [male, female, other], message: Choose a valid gender. }
            # ...
    Annotations:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Constraints as Assert; class Author{
        /**
         * @Assert\Choice(
         *     choices = { "male", "female", "other" },
         *     message = "Choose a valid gender."
         * )
         */
        public $gender;     // ...}

    Constraint options can always be passed through an array. Some constraints also allow you to pass a value for the "default" option in place of this array. In Choice constraints, choices options can be specified in this way.

    PHP:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints as Assert; class Author{
        protected $gender;     public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            // ...         $metadata->addPropertyConstraint(
                'gender',
                new Assert\Choice(array('male', 'female', 'other'))
            );
        }}
    XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8" ?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">     <class name="AppBundle\Entity\Author">
            <property name="gender">
                <constraint name="Choice">
                    <value>male</value>
                    <value>female</value>
                    <value>other</value>
                </constraint>
            </property>         <!-- ... -->
        </class></constraint-mapping>
    YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Author:
        properties:
            gender:
                - Choice: [male, female, other]
            # ...
    Annotations:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Constraints as Assert; class Author{
        /**
         * @Assert\Choice({"male", "female", "other"})
         */
        protected $gender;     // ...}

    This is purely to make the most common configuration options easier and faster to use.

    If you are not sure how to specify an option, either check the API documentation, or just to be on the safe side, pass it in through an options array (i.e. the first method above).

    Goals of constraints

    Constraints can be applied to class properties (such as name) or to a public getter method (such as getFullName) or even the entire class. Attribute constraints are the most commonly used and simplest, while Getter constraints allow you to specify more complex validation rules. Finally, if the use case for class constraints is that you want to verify the class as a whole.

    Attribute constraints

    The verification of class attributes is one of the most basic verification techniques. Symfony allows you to verify private, protected or public properties. The following code shows how to configure the $firstName property of the Author object so that it has at least 3 characters:

    PHP:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints as Assert; class Author{
        private $firstName;     public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addPropertyConstraint('firstName', new Assert\NotBlank());
            $metadata->addPropertyConstraint(
                'firstName',
                new Assert\Length(array("min" => 3))
            );
        }}
    XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8" ?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">     <class name="AppBundle\Entity\Author">
            <property name="firstName">
                <constraint name="NotBlank" />
                <constraint name="Length">
                    <option name="min">3</option>
                </constraint>
            </property>
        </class></constraint-mapping>
    YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Author:
        properties:
            firstName:
                - NotBlank: ~
                - Length:
                    min: 3
    Annotations:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Constraints as Assert; class Author{
        /**
         * @Assert\NotBlank()
         * @Assert\Length(min=3)
         */
        private $firstName;}

    Getters Constraints

    Constraints can also be applied to the return value of a method. Symfony allows you to add a constraint to any public method that begins with "get", "is" or "has". This type of method is called "getters".

    The benefit of this technique is that it allows you to dynamically validate your objects. For example, suppose you want to ensure that the password field does not match the user's firstname (for security reasons). You can do this by creating a isPasswordLegal method and then asserting that the method must return true:

    PHP:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Mapping\ClassMetadata;use Symfony\Component\Validator\Constraints as Assert; class Author{
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addGetterConstraint('passwordLegal', new Assert\IsTrue(array(
                'message' => 'The password cannot match your first name',
            )));
        }}
    XML:<!-- src/AppBundle/Resources/config/validation.xml --><?xml version="1.0" encoding="UTF-8" ?><constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">     <class name="AppBundle\Entity\Author">
            <getter property="passwordLegal">
                <constraint name="IsTrue">
                    <option name="message">The password cannot match your first name</option>
                </constraint>
            </getter>
        </class></constraint-mapping>
    YAML:# src/AppBundle/Resources/config/validation.ymlAppBundle\Entity\Author:
        getters:
            passwordLegal:
                - 'IsTrue': { message: 'The password cannot match your first name' }
    Annotations:// src/AppBundle/Entity/Author.php // ...use Symfony\Component\Validator\Constraints as Assert; class Author{
        /**
         * @Assert\IsTrue(message = "The password cannot match your first name")
         */
        public function isPasswordLegal()
        {
            // ... return true or false
        }}

    Now, create a isPasswordLegal() Method, containing the logic you need:

    public function isPasswordLegal(){
        return $this->firstName !== $this->password;}


    Those with a sharp eye may notice that in the constraint configuration format of YAML, XML and PHP , the getter prefix ("get", "is" or "has") is ignored when mapping. This allows you to move a constraint to a subsequent property of the same name (or vice versa) without changing the validation logic.


    Class constraints

    There are some constraints that can be applied to the entire class being verified. For example, a constraint of type Callback is a general constraint that can be applied to the class itself. When a class is validated, the methods specified by the constraints will be executed directly to provide more custom validation.

    Summary

    Symfony's validator (validation) is a powerful tool that can be used to ensure that the data of any object is legal. sex. Its power comes from constraints, which you can apply to object properties and getter methods. Although, in most cases, the validation framework is applied indirectly when using forms, remember, it can be used anywhere to validate any object.

    ##
    1
    2
    AppBundle\Author.name:
      This value should not be blank