SoFunction
Updated on 2025-04-04

Example analysis of Symfony data verification method

This article describes the Symfony data verification method. Share it for your reference. The specific analysis is as follows:

Verification is a common task in web applications. Data input to the form needs to be verified. Data needs to be verified before being written to the database or when passed into a webservice.

Symfony2 comes with a Validator component, which makes verification work simple and easy to understand. This component is based on the JSR303 Bean verification specification. A Java specification is used in PHP.

Basic Verification

The best way to understand verification is to see its performance. First, suppose you have created a PHP object for somewhere in your application.

Copy the codeThe code is as follows:
//src/Acme/BlogBundle/Entity/
namespace Acme\BlogBundle\Entity;

class Author
{
    public $name;
}

Until now, it's just a normal class that serves some purposes of your application. The purpose of verification is to tell you whether the object's data is legal. For this purpose, you need to configure an object that must comply with rules or constraint lists to make your data legal. These rules can be described in many different formats (e.g., YAML, XML, class declaration or PHP). For example, we ensure that the property $name cannot be empty, so we add the following rules:

YAML format:

Copy the codeThe code is as follows:
# src/Acme/BlogBundle/Resources/config/
Acme\BlogBundle\Entity\Author:
    properties:
         name:
            - NotBlank: ~

Class declaration format:
Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/
use Symfony\Component\Validator\Constraints as Assert;

class Author
{
   /**
    * @Assert\NotBlank()
    */
    public $name;
}

XML format:

Copy the codeThe code is as follows:
<!-- src/Acme/BlogBundle/Resources/config/ -->
<?xml version="1.0" encoding="UTF-8" ?>
<constraint-mapping xmlns="/schema/dic/constraint-mapping"
    xmlns:xsi="http:///2001/XMLSchema-instance"
    xsi:schemaLocation="/schema/dic/constraint-mapping /schema/dic/constraint-mapping/constraint-mapping-1.">

    <class name="Acme\BlogBundle\Entity\Author">
        <property name="name">
            <constraint name="NotBlank" />
        </property>
    </class>
</constraint-mapping>

PHP code format:

Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/

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());
   }
}

The Protected and private properties and getter methods can also be verified.

Use validator service:

Next, use the validate method of the validator service to truly verify the Author object. The validator's job is simple: read the constraint rules of a class to verify whether the data of an object complies with these rules. If the check fails, an error array will be returned. Now we execute it in a controller:

Copy the codeThe code is as follows:
use Symfony\Component\HttpFoundation\Response;
use Acme\BlogBundle\Entity\Author;
//...

public function indexAction()
{
   $author = new Author();
//... What to do with the $auother object
  
   $validator = $this->get('validator');
   $errors = $validator->validate($author);

   if(count($errors) >0){
     return new Response(print_r($errors, true));
   }else{
     return new Response('The author is valid! Yes!');
   }
}

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

Acme\BlogBundle\:
     This value should not be blank

If you insert a value for the $name property, you will get happy success information.

Most of the time, you don't need to communicate directly with the validator service or you don't have to worry about printing errors at all.

In most cases, you will use verification when processing the submitted form data.

You can also pass an error message collection into a template:

Copy the codeThe code is as follows:
if(count($errors)>0){
   return $this->render('AcmeBlogBundle:Author:',array(
        'errors' => $errors,
   ));
}else{
  //...
}

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

Twig format:

Copy the codeThe code is as follows:
{# src/Acme/BlogBundle/Resources/views/Author/ #}
<h3>The author has the following errros</h3>
<ul>
{% for error in errors %}
    <li>{{ }}</li>
{% endfor %}
</ul>

Checksum Form

The validator service can be used to verify any object at any time. In fact, you will often use validator at the time of processing form. Symfony's form class library indirectly uses the validator service to verify the underlying object after the data is submitted and bound. The object's violation of constraint information will be converted to the FieldError object, which can be easily displayed in your form. The traditional form submission process in a controller is as follows:

Copy the codeThe code is as follows:
use Acme\BlogBundle\Entity\Author;
use Acme\BlogBundle\Form\AuthorType;
use Acme\Component\HttpFoundation\Request;
//...

public function updateAction(Request $request)
{
    $author = new Acme\BlogBundle\Entity\Author();
    $form = $this->createForm(new AuthorType(),$author);

    if($request->getMethod() =='POST'){
       $form->bindRequest($request);
 
       if($form->isvalid()){
//Do some operations on $author
          return $this->redirect($this->generateUrl('...'));
       }
     }

     return $this->render('BlogBundle:Author:',array(
         'form' => $form->createView(),
     ));
}

Configuration:

Symfony2's validator is available by default. But if you use the life method to specify your constraints, you need to explicitly enable the declaration function:

YAML format:

Copy the codeThe code is as follows:
# app/config/
framework:
   validation: {enable_annotations: true }

XML format:
Copy the codeThe code is as follows:
<!-- app/config/ -->
<framework:config>
   <framework:validation enable-annotations="true" />
</framework:config>

PHP code format:
Copy the codeThe code is as follows:
// app/config/
$contianer->loadFromExtension('framework',array('validation'=> array(
     'enable_annotations'=>true,
)));

Constraint rules

Validator is designed to verify objects according to constraint rules. In order to verify an object, you only need to map one or more constraints to the class it wants to verify and pass it to the validator service.

Essentially, a constraint is a simple PHP object that can generate a decision statement. In real life, a constraint can be a rule constraint such as "the cake cannot be scorched". In Symfony2, the constraints are almost the same: they decide whether a certain condition is true. Given a value, the constraint will tell you whether the value complies with your constraint rules.

Symfony2 supports constraint rules

First of all, the basic constraint rules: use them to decide very basic things, such as the value of your object's attributes or the return value of the method.

NotBlank,Blank,NotNull,Null,True,False,Type

String constraints: Email, MinLength, MaxLength, Url, Regex, Ip, etc.
Number constraints: Max, Min
Date constraints: Date, DateTime and Time
Collection constraints: Choice, Collection, UniqueEntity, Language, Locale and Country, etc.
File constraints: File, Image
Other constraints: Callback, All, Valid

You can also create your own custom constraints.

Constraint configuration:

Some constraints, such as NotBlank, are simple, but others, such as Choice constraints, have many configuration items that need to be set. Assuming that the Author class has another property, the generator can be set to "male" or "female":

YAML format:

Copy the codeThe code is as follows:
# src/Acme/BlogBundle/Resources/config/
Acme\BlogBundle\Entity\Author:
    properties:
         gener:
            - Choice: { choices: [male, female], message: Choos a valid gender. }

Class declaration format:
Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/
use Symfony\Component\Validator\Constraints as Assert;

class Author
{
   /**
    * @Assert\Choice(
    *     choices = {"male","female"},
    *     message = "Choose a valid gender."
    * )
    */
    public $gender;
}

XML format:

Copy the codeThe code is as follows:
<!-- src/Acme/BlogBundle/Resources/config/ -->
<?xml version="1.0" encoding="UTF-8" ?>
<constraint-mapping xmlns="/schema/dic/constraint-mapping"
    xmlns:xsi="http:///2001/XMLSchema-instance"
    xsi:schemaLocation="/schema/dic/constraint-mapping /schema/dic/constraint-mapping/constraint-mapping-1.">

    <class name="Acme\BlogBundle\Entity\Author">
        <property name="gender">
            <constraint name="Choice">
                <option name="choices">
                    <value>male</value>
                    <value>female</value>
                </option>
                <option name="message">Choose a valid gender.</option>
            </constraint>
        </property>
    </class>
</constraint-mapping>

PHP code format:

Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;

class Author
{
    public $gender;

    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('gender', new Choice(array(
            'choices' => array('male', 'female'),
            'message' => 'Choose a valid gender.',
        )));
    }
}

An option for a constraint is usually passed through an array. Some constraints also allow you to pass a value. "default" is optional in the array. When Choice constraints, the choices option can be specified in this way.

YAML format:

Copy the codeThe code is as follows:
# src/Acme/BlogBundle/Resources/config/
Acme\BlogBundle\Entity\Author:
    properties:
        gender:
            - Choice: [male, female]

Class declaration format:
Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/
use Symfony\Component\Validator\Constraints as Assert;

class Author
{
    /**
     * @Assert\Choice({"male", "female"})
     */
    protected $gender;
}

XML format:

Copy the codeThe code is as follows:
<!-- src/Acme/BlogBundle/Resources/config/ -->
<?xml version="1.0" encoding="UTF-8" ?>
<constraint-mapping xmlns="/schema/dic/constraint-mapping"
    xmlns:xsi="http:///2001/XMLSchema-instance"
    xsi:schemaLocation="/schema/dic/constraint-mapping /schema/dic/constraint-mapping/constraint-mapping-1.">

    <class name="Acme\BlogBundle\Entity\Author">
        <property name="gender">
            <constraint name="Choice">
                <value>male</value>
                <value>female</value>
            </constraint>
        </property>
    </class>
</constraint-mapping>

PHP format:

Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\Choice;

class Author
{
    protected $gender;

    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('gender', new Choice(array('male', 'female')));
    }
}

Constrain the target

Constraints can be used for properties of a class or for a public getter method. Attribute constraints are the most commonly used and simplest, while public getter method constraints allow you to specify a complex constraint rule.

Attribute constraints:

The most common verification technique for the property stone of the verification class. Symfony2 allows you to verify private, protected or public properties. The following code shows how to configure the Author object's $firstName property to have at least 3 characters:

YAML format:

Copy the codeThe code is as follows:
# src/Acme/BlogBundle/Resources/config/
Acme\BlogBundle\Entity\Author:
    properties:
        firstName:
            - NotBlank: ~
            - MinLength: 3

Class declaration format:
Copy the codeThe code is as follows:
// Acme/BlogBundle/Entity/
use Symfony\Component\Validator\Constraints as Assert;

class Author
{
    /**
     * @Assert\NotBlank()
     * @Assert\MinLength(3)
     */
    private $firstName;
}

XML format:

Copy the codeThe code is as follows:
<!-- src/Acme/BlogBundle/Resources/config/ -->
<class name="Acme\BlogBundle\Entity\Author">
    <property name="firstName">
        <constraint name="NotBlank" />
        <constraint name="MinLength">3</constraint>
    </property>
</class>

PHP code format:

Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\MinLength;

class Author
{
    private $firstName;

    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('firstName', new NotBlank());
        $metadata->addPropertyConstraint('firstName', new MinLength(3));
    }
}

Getters

Constraints can also be applied to the return value of a method. Symfony2 allows you to add a constraint to any public method that starts with "get" or "is". The advantage of this technology is that it allows you to dynamically verify your objects. For example, suppose you want to confirm that the password field does not match the user's first name (for security reasons). You can create an idPasswordLegal method and then decide that this method must return true:

YAML format:

Copy the codeThe code is as follows:
# src/Acme/BlogBundle/Resources/config/
Acme\BlogBundle\Entity\Author:
    getters:
        passwordLegal:
            - "True": { message: "The password cannot match your first name" }

Class declaration format:
Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/
use Symfony\Component\Validator\Constraints as Assert;

class Author
{
    /**
     * @Assert\True(message = "The password cannot match your first name")
     */
    public function isPasswordLegal()
    {
        // return true or false
    }
}

XML format:

Copy the codeThe code is as follows:
<!-- src/Acme/BlogBundle/Resources/config/ -->
<class name="Acme\BlogBundle\Entity\Author">
    <getter property="passwordLegal">
        <constraint name="True">
            <option name="message">The password cannot match your first name</option>
        </constraint>
    </getter>
</class>

PHP code format:

Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\True;

class Author
{
    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addGetterConstraint('passwordLegal', new True(array(
            'message' => 'The password cannot match your first name',
        )));
    }
}

Now we create an isPasswordLegal() method and include the logic you need:

Copy the codeThe code is as follows:
public function isPasswordLegal()
{
   return ($this->firstName != $this->password);
}

A sharp-eyed person may notice that the getter's prefix ("get" or "is") is ignored when mapping. This allows you to move a constraint to a property with the same name without changing the verification rules, and vice versa.

kind:

Some constraints are applied to the entire class being verified. For example, the Callback constraint is a general constraint that can be applied to the class itself. When the class is verified, the methods described by the constraint are simply executed so that each can provide a more personalized verification.

Verify grouping

So far, you have been able to add constraints to the class and ask if the class passes in all defined constraint rules. In some cases, you only need to use some of the rules of the class to verify an object. To do this, you can organize each constraint into one or more verification groups and then apply using one of the verifications. For example, suppose you have a User class that will be used when the user registers and the user updates their contact information.

YAML format:

Copy the codeThe code is as follows:
# src/Acme/BlogBundle/Resources/config/
Acme\BlogBundle\Entity\User:
    properties:
        email:
            - Email: { groups: [registration] }
        password:
            - NotBlank: { groups: [registration] }
            - MinLength: { limit: 7, groups: [registration] }
        city:
            - MinLength: 2

Class declaration format:

Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/
namespace Acme\BlogBundle\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;

class User implements UserInterface
{
    /**
    * @Assert\Email(groups={"registration"})
    */
    private $email;

    /**
    * @Assert\NotBlank(groups={"registration"})
    * @Assert\MinLength(limit=7, groups={"registration"})
    */
    private $password;

    /**
    * @Assert\MinLength(2)
    */
    private $city;
}

XML format:

Copy the codeThe code is as follows:
<!-- src/Acme/BlogBundle/Resources/config/ -->
<class name="Acme\BlogBundle\Entity\User">
    <property name="email">
        <constraint name="Email">
            <option name="groups">
                <value>registration</value>
            </option>
        </constraint>
    </property>
    <property name="password">
        <constraint name="NotBlank">
            <option name="groups">
                <value>registration</value>
            </option>
        </constraint>
        <constraint name="MinLength">
            <option name="limit">7</option>
            <option name="groups">
                <value>registration</value>
            </option>
        </constraint>
    </property>
    <property name="city">
        <constraint name="MinLength">7</constraint>
    </property>
</class>

PHP code format:

Copy the codeThe code is as follows:
// src/Acme/BlogBundle/Entity/
namespace Acme\BlogBundle\Entity;

use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\MinLength;

class User
{
    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('email', new Email(array(
            'groups' => array('registration')
        )));

        $metadata->addPropertyConstraint('password', new NotBlank(array(
            'groups' => array('registration')
        )));
        $metadata->addPropertyConstraint('password', new MinLength(array(
            'limit'  => 7,
            'groups' => array('registration')
        )));

        $metadata->addPropertyConstraint('city', new MinLength(3));
    }
}

Here we have configured two verification groups:
default default group: Includes all constraint rules that are not assigned to any group
Registration: Only the verification rules for email and password fields are included

Tell the validator to use the specified verification group and pass one or more group names as the second parameter of the validate() method:

Copy the codeThe code is as follows:
$errors = $validator->validate($author,array('registration'));

Value and array verification

So far, we've seen how to verify the entire object. But sometimes, we might want to check a value for a separate value, such as checking whether a string is a legal email address. This is very simple, and it is done as follows in the Controller class:

Copy the codeThe code is as follows:
// Reference the corresponding verification namespace before the controller class
use Symfony\Component\Validator\Constraints\Email;

public function addEmailAction($email)
{
    $emailConstraint = new Email();
// All verification options (options) can be set in this way
    $emailConstraint->message = 'Invalid email address';

// Use validator to verify a value
    $errorList = $this->get('validator')->validateValue($email, $emailConstraint);

    if (count($errorList) == 0) {
// This is a legal email address, what can I do
    } else {
// This is an illegal email address
        $errorMessage = $errorList[0]->getMessage()

// Do some error handling
    }

    // ...
}

By calling the validateValue method of validator, you can pass in a raw value and a verification object you want to use. This method returns a ConstraintViolationList object, which only plays the role of an array of error messages. Each error in the collection is a ConstraintViolation object. Use the getMessage method of the object to get the error information.

Summarize:

Symfony2's validator is a powerful tool that can be used to ensure the legitimacy of any object data. Its power comes from constraint rules, which you can apply to your object's properties and getter methods. In fact, in most cases, you use the verification framework indirectly when using the form, remember that it can be applied to verify any object anywhere.

I hope this article will be helpful to everyone's Symfony framework programming.