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:
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('name', 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('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 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('AcmeBlogBundle:Author:validate.html.twig',array( 'errors' => $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
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()){ //对$author做一些操作 return $this->redirect($this->generateUrl('...')); } } return $this->render('BlogBundle:Author:form.html.twig',array( 'form' => $form->createView(), )); }
# app/config/config.yml framework: validation: {enable_annotations: true }
The code is as follows:
// app/config/config.php $contianer->loadFromExtension('framework',array('validation'=> array( 'enable_annotations'=>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, MinDate constraints: Date, DateTime and Time
Collection constraints: Choice, Collection, UniqueEntity, Language, Locale and Country, etc.
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. }
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:
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('gender', new Choice(array( 'choices' => array('male', 'female'), 'message' => 'Choose a valid gender.', ))); } }
一个约束的选项通常都是通过一个数组来传递的。有些约束也允许你传递一个值。"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格式:
代码如下:
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('gender', new Choice(array('male', 'female'))); } }
约束目标
约束可以被用于一个类的属性或者一个公共的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('firstName', new NotBlank()); $metadata->addPropertyConstraint('firstName', 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('passwordLegal', new True(array( 'message' => 'The password cannot match your first name', ))); } }
现在我们创建一个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('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)); } }
这里我们配置了两个校验组:
default默认组: 包括所有没有分配到任何组的约束规则
registration: 只包含了email和password字段的校验规则
告诉validator使用指定的校验组,传一个或者多个组名作为validate()方法的第二个参数即可:
代码如下:
$errors = $validator->validate($author,array('registration'));
值和数组校验
到目前为止,我们已经看了如何校验整个对象。但是有时候,我们可能想值校验一个单独的值,比如校验一个字符串是不是一个合法的email地址。这非常简单,在Controller类中进行如下:
代码如下:
// 在controller类前引用相应的校验命名空间 use Symfony\Component\Validator\Constraints\Email; public function addEmailAction($email) { $emailConstraint = new Email(); // 所有的校验选项(options)都可以这样设置 $emailConstraint->message = 'Invalid email address'; // 使用validator来校验一个值 $errorList = $this->get('validator')->validateValue($email, $emailConstraint); if (count($errorList) == 0) { // 这是一个合法的email地址,可以做些什么 } else { // 这是一个非法的email地址 $errorMessage = $errorList[0]->getMessage() // 做一些错误处理 } // ... }
通过调用validator的validateValue方法,你可以传入一个原始值和一个你要使用的校验对象。该方法会返回一个ConstraintViolationList对象,它扮演的只是一个错误信息数组的角色。集合中的每一个错误是一个ConstraintViolation对象,使用对象的getMessage方法可以获取错误信息。
总结:
Symfony2 的validator是一个强大的工具,它可以被用来保证任何对象数据的合法性。它的强大来源于约束规则,你可以把它们应用于你对象的属性和getter方法。其实,你大多数情况下都是在使用表单时,间接的应用了校验框架,记住它可以被应用于任何地方校验任何对象。
相关推荐:
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!