Home  >  Article  >  Backend Development  >  Symfony data verification method analysis

Symfony data verification method analysis

不言
不言Original
2018-03-29 16:53:011406browse

This article uses examples to analyze the Symfony data verification method. It is shared here for your reference. Interested friends can take a look at


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

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

Basic Verification

The best way to understand verification is to see how it performs. First, assume that you have created a PHP object that is used somewhere in your application.

The code is as follows:

//src/Acme/BlogBundle/Entity/Author.php
namespace Acme\BlogBundle\Entity;
class Author
{
public $name;
}


Up to now, it is just an ordinary class that serves some purpose 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 to follow a list of rules or constraints to make its data legal. These rules can be described in many different formats (e.g., YAML, XML, class declarations or PHP). For example, we ensure that the attribute $name cannot be empty, so add the following rules:

YAML format:

The code is as follows:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
properties:
name:
- NotBlank: ~


Class declaration Format:

The code is as follows:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* @Assert\NotBlank()
*/
public $name;
}

XML format:

The code is as follows:

<?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">

PHP code format:

The code is as follows:

// src/Acme/BlogBundle/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(&#39;name&#39;, new NotBlank());
}
}

Protected and private attributes and getter methods can also be verified.

Use the validator service:

Next, use the validate method of the validator service to actually 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 conforms to these rule constraints. If validation fails, an error array will be returned. Now we execute it in a controller:

The code is as follows:

use Symfony\Component\HttpFoundation\Response;
use Acme\BlogBundle\Entity\Author;
//...
public function indexAction()
{
$author = new Author();
//... 对$auother对象做些什么

$validator = $this->get(&#39;validator&#39;);
$errors = $validator->validate($author);
if(count($errors) >0){
return new Response(print_r($errors, true));
}else{
return new Response(&#39;The author is valid! Yes!&#39;);
}
}


If the $name attribute is empty, you will see the following Error message:

Acme\BlogBundle\Author.name:
This value should not be blank

If you insert a value for the $name attribute, then you will have happy success information.

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

In most cases, you will use validation indirectly when processing submitted form data.

You can also pass a collection of error messages to a template:

The code is as follows:

if(count($errors)>0){
return $this->render(&#39;AcmeBlogBundle:Author:validate.html.twig&#39;,array(
&#39;errors&#39; => $errors,
));
}else{
//...
}


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

Twig format:

The code is as follows:

{# src/Acme/BlogBundle/Resources/views/Author/validate.html.twig #}
The author has the following errros
{% for error in errors %}
{{ error.message }}
{% endfor %}

Checksum form

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


The 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() ==&#39;POST&#39;){
$form->bindRequest($request);

if($form->isvalid()){
//对$author做一些操作
return $this->redirect($this->generateUrl(&#39;...&#39;));
}
}
return $this->render(&#39;BlogBundle:Author:form.html.twig&#39;,array(
&#39;form&#39; => $form->createView(),
));
}

Configuration:

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

YAML format:


The code is as follows:

# app/config/config.yml
framework:
validation: {enable_annotations: true }

XML format:


The code is as follows:




##PHP code format:



The code is as follows:

// app/config/config.php
$contianer->loadFromExtension(&#39;framework&#39;,array(&#39;validation&#39;=> array(
&#39;enable_annotations&#39;=>true,
)));

Constraint rules

Validator is designed to verify objects according to constraint rules. To validate an object, just map one or more constraints to the class it is validating and pass it to the validator service.

Essentially, a constraint is a simple PHP object that generates a decision statement. In real life, a constraint can be a rule constraint such as "the cake cannot be burned". In Symfony2, constraints are all the same: they determine whether a certain condition is true or not. Given a value, the constraint tells you whether the value obeys your constraint rules.

Constraint rules supported by Symfony2

The first is the basic constraint rules: use them to determine very basic things, such as the value of your object's property or the return value of a method.

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

String constraints: Email, MinLength, MaxLength, Url, Regex, Ip, etc.

Numeric 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 very simple, but others, such as Choice constraints, have many configuration items that need to be set. Assuming that the Author class has another attribute, gener can be set to "male" or "female":

YAML format:


The code is as follows:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
properties:
gener:
- Choice: { choices: [male, female], message: Choos a valid gender. }

Class declaration format:



The code is as follows:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* @Assert\Choice(
* choices = {"male","female"},
* message = "Choose a valid gender."
* )
*/
public $gender;
}


XML format:


The code is as follows:

<?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">

PHP code format:


The code is as follows:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;
class Author
{
public $gender;
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint(&#39;gender&#39;, new Choice(array(
&#39;choices&#39; => array(&#39;male&#39;, &#39;female&#39;),
&#39;message&#39; => &#39;Choose a valid gender.&#39;,
)));
}
}

一个约束的选项通常都是通过一个数组来传递的。有些约束也允许你传递一个值。"default"在数组中是可选的。在Choice约束时,choices选项就可以通过这种方式指定。

YAML格式:

代码如下:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
properties:
gender:
- Choice: [male, female]

类声明格式:

代码如下:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* @Assert\Choice({"male", "female"})
*/
protected $gender;
}

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">
male
female

PHP格式:

代码如下:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\Choice;
class Author
{
protected $gender;
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint(&#39;gender&#39;, new Choice(array(&#39;male&#39;, &#39;female&#39;)));
}
}


约束目标

约束可以被用于一个类的属性或者一个公共的getter方法。属性约束最常用也最简单,而公共的getter方法约束则允许你指定一个复杂的约束规则。

属性约束:

校验类的属性石一个最常规的校验技术。Symfony2允许你校验private,protected或者public属性。下面代码显示如何配置Author对象的$firstName属性至少有3个字符:

YAML格式:

代码如下:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
properties:
firstName:
- NotBlank: ~
- MinLength: 3


类声明格式:

代码如下:

// Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* @Assert\NotBlank()
* @Assert\MinLength(3)
*/
private $firstName;
}


XML格式:

代码如下:





3


PHP代码格式:

代码如下:

// src/Acme/BlogBundle/Entity/Author.php
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(&#39;firstName&#39;, new NotBlank());
$metadata->addPropertyConstraint(&#39;firstName&#39;, new MinLength(3));
}
}

Getters

约束也可以应用于一个方法的返回值。Symfony2 允许你添加一个约束到任何"get"或者 "is"开头的public方法。该技术的好处是允许你动态的校验你的对象。比如,假设你想确认密码字段不匹配用户的first name(因为安全原因)。你可以通过创建一个idPasswordLegal 方法,然后决断这个方法必须返回true:

YAML格式:

代码如下:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\Author:
getters:
passwordLegal:
- "True": { message: "The password cannot match your first name" }

类声明格式:

代码如下:

// src/Acme/BlogBundle/Entity/Author.php
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格式:

代码如下:


PHP代码格式:

代码如下:

// src/Acme/BlogBundle/Entity/Author.php
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\True;
class Author
{
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addGetterConstraint(&#39;passwordLegal&#39;, new True(array(
&#39;message&#39; => &#39;The password cannot match your first name&#39;,
)));
}
}

现在我们创建一个isPasswordLegal()方法,并且包含你需要逻辑:

代码如下:

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

眼尖的人可能会注意到getter的前缀("get"或者"is")在映射时被忽略了。这允许你在不改变校验规则的前提下,把一个约束移动到一个具有同名属性上,反之亦然。


类:

一些约束应用到整个类被校验上面。比如,Callback约束是一个通用约束,它可以应用到类自身。当类被校验时,被约束描述的方法只是被执行这样每一个可以提供更个性化的校验。

校验分组

到目前为止,你已经能够添加约束到类并询问是否该类传入所有定义的约束规则。一些情况下,你只需要使用该类的其中某些规则来校验一个对象。要做到这些,你可以组织每一个约束到一个或者多个校验组中,然后应用使用其中一组校验。比如,假设你有一个User类,它会在用户注册和用户更新他们的联系信息时使用。

YAML格式:

代码如下:

# src/Acme/BlogBundle/Resources/config/validation.yml
Acme\BlogBundle\Entity\User:
properties:
email:
- Email: { groups: [registration] }
password:
- NotBlank: { groups: [registration] }
- MinLength: { limit: 7, groups: [registration] }
city:
- MinLength: 2


类声明格式:

代码如下:

// src/Acme/BlogBundle/Entity/User.php
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格式:

代码如下:

7

PHP代码格式:

代码如下:

// src/Acme/BlogBundle/Entity/User.php
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(&#39;email&#39;, new Email(array(
&#39;groups&#39; => array(&#39;registration&#39;)
)));
$metadata->addPropertyConstraint(&#39;password&#39;, new NotBlank(array(
&#39;groups&#39; => array(&#39;registration&#39;)
)));
$metadata->addPropertyConstraint(&#39;password&#39;, new MinLength(array(
&#39;limit&#39; => 7,
&#39;groups&#39; => array(&#39;registration&#39;)
)));
$metadata->addPropertyConstraint(&#39;city&#39;, new MinLength(3));
}
}

这里我们配置了两个校验组:
default默认组: 包括所有没有分配到任何组的约束规则
registration: 只包含了email和password字段的校验规则

告诉validator使用指定的校验组,传一个或者多个组名作为validate()方法的第二个参数即可:

代码如下:

$errors = $validator->validate($author,array(&#39;registration&#39;));

值和数组校验

到目前为止,我们已经看了如何校验整个对象。但是有时候,我们可能想值校验一个单独的值,比如校验一个字符串是不是一个合法的email地址。这非常简单,在Controller类中进行如下:

代码如下:

// 在controller类前引用相应的校验命名空间
use Symfony\Component\Validator\Constraints\Email;
public function addEmailAction($email)
{
$emailConstraint = new Email();
// 所有的校验选项(options)都可以这样设置
$emailConstraint->message = &#39;Invalid email address&#39;;
// 使用validator来校验一个值
$errorList = $this->get(&#39;validator&#39;)->validateValue($email, $emailConstraint);
if (count($errorList) == 0) {
// 这是一个合法的email地址,可以做些什么
} else {
// 这是一个非法的email地址
$errorMessage = $errorList[0]->getMessage()
// 做一些错误处理
}
// ...
}


通过调用validator的validateValue方法,你可以传入一个原始值和一个你要使用的校验对象。该方法会返回一个ConstraintViolationList对象,它扮演的只是一个错误信息数组的角色。集合中的每一个错误是一个ConstraintViolation对象,使用对象的getMessage方法可以获取错误信息。

总结:

Symfony2 的validator是一个强大的工具,它可以被用来保证任何对象数据的合法性。它的强大来源于约束规则,你可以把它们应用于你对象的属性和getter方法。其实,你大多数情况下都是在使用表单时,间接的应用了校验框架,记住它可以被应用于任何地方校验任何对象。

相关推荐:

Symfony查询方法小结分享

Symfony2针对输入时间进行查询实例详解

详解Symfony2框架表单的用法

The above is the detailed content of Symfony data verification method analysis. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn