验证是Web应用程序中非常常见的任务。填入表单的数据需要验证,在它们被写入数据库或被发送给Web服务时也需要验证。

Symfony2附带的Validator组件使这个任务变得简单和透明。该组件基于JSR303 Bean验证规范。什么?在PHP中使用JAVA规范?你没听错,但它并不象听上去那么糟。让我们看看它是怎么在PHP使用的。

验证基础

最好的理解验证的方式就是在实战中学习。开始先假设你已经创建了一个简单PHP对象(plain-old-PHP-Object,简称POPO),你需要它在你应用程序中使用:

  1. // Acme/BlogBundle/Author.php 
  2. class Author 
  3.     public $name

目前为止,这还只是个普通的类,它在你的应用程序中实现一些目标。验证的目的就是要告诉你对象中的数据是否合法。为了能够进行验证,你需要配置一个对象必须遵循的规则列表(称为限制)。这些规则可以通过不同的格式(YAML、XML、注释或PHP)来指定。为了保证$name属性非空,必须添加下列内容:

  1. # Acme/BlogBundle/Resources/config/validation.yml 
  2. Acme\BlogBundle\Author: 
  3.     properties: 
  4.         name
  5.             - NotBlank: ~ 

象“getter“一样,保护和私有属性也可以被验证(参见validator-constraint-targets)

使用验证服务

要验证Author对象,需要使用验证服务(Validator类)的validate方法。验证工作的容易的:查看类限制(如规则)并验证对象数据是否符合那些限制。如果验证失败,则返回一个错误数组。下面的来自控制器内部的简单示例:

  1. use Symfony\Component\HttpFoundation\Response; 
  2. // ... 
  3.  
  4. public function indexAction() 
  5.     $author = new Acme\BlogBundle\Author(); 
  6.     // ... do something to the $author object 
  7.  
  8.     $validator = $container->get('validator'); 
  9.     $errorList = $validator->validate($author); 
  10.  
  11.     if (count($errorList) > 0) { 
  12.         return new Response(print_r($errorList, true)); 
  13.     } else { 
  14.         return new Response('The author is valid! Yes!'); 
  15.     } 

 如果$name属性为空,你将看到如下错误信息:

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

 如果你在name属性中插入值,那么得会出现验证成功的消息。

每个验证错误(称为“违反限制“),是由ConstraintViolation对象表现,该对象保持着一个描述错误的消息。此外validate方法返回一个类数组的ConstraintVoilationList对象。你还有很长的路要走,你可以用更先进的方式来使用验证并返回的错误。你可以先着色一个模板并将$errorList变量发送其中:

  1. if (count($errorList) > 0) { 
  2.     return $this->render('AcmeBlogBundle:Author:validate.html.twig'array
  3.         'errorList' => $errorList
  4.     )); 
  5. else { 
  6.     // ... 

在模板中,你可以只输出你所需要的错误列表:

  1. {# src/Acme/BlogBundle/Resources/views/Author/validate.html.twig #} 
  2.  
  3. <h3>The author has the following errors</h3> 
  4. <ul> 
  5. {% for error in errorList %} 
  6.     <li>{{ error.message }}</li> 
  7. {% endfor %} 
  8. </ul> 

 验证和表单

无论何时,验证服务都可以用于验证任何对象。然而,实际上,你通常会通过Form类间接地使用验证。Form类使用验证服务在值被提交或约束时去验证底层对象。对象的限制约束被转换成FieldError对象,然后显示在你的表单中:

  1. $author = new Acme\BlogBundle\Author(); 
  2. $form = new Acme\BlogBundle\AuthorForm('author'$author$this->get('validator')); 
  3. $form->bind($this->get('request')->request->get('customer')); 
  4.  
  5. if ($form->isValid()) { 
  6.     // process the Author object 
  7. else { 
  8.     // render the template with the errors 
  9.     $this->render('BlogBundle:Author:form.html.twig'array('form' => $form)); 

详情请参见表单章节。

配置

要使用Symfony2验证,需要确定它在你的应用程序配置中是可用的。

  1. # hello/config/config.yml 
  2. framework: 
  3.     validation: { enabled: true, annotations: true } 

如果你是通过注释映射限制的话,那么只需要将注释配置设置成true。

限制

验证是被设计用来验证对象是否违反限制(如规则)。要验证一个对象,只需简单地映射一个或多个限制到它的类,然后将其发送给验证服务。

限制简单地说是一个PHP对象,它生成一个限制规则的声明。在现实生活中,限制可以是“蛋糕不能燃烧”。在Symfony2中,限制也是相似的:它们被声明条件为真。指定一个值,限制将告诉你该值是否符合限制的规则。

限制支持

Symfony2包括了大量的常规限制。有关限制细节的完整列表可以在限制参考一节中找到。

配置限制

一些限制,如非空,是简单的。而其它的,如选择限制,则拥有几个可用的配置选项。这些可用选项在限制中是公共属性。通过发送一个选项数组给限制,它们中的每一个都可以被设置。假设Author类有另一个性别属性,该属性可以被设置成“男”或“女”:

  1. # Acme/BlogBundle/Resources/config/validation.yml 
  2. Acme\BlogBundle\Author: 
  3.     properties: 
  4.         gender: 
  5.             - Choice: { choices: [male, female], message: Choose a valid gender. } 

限制选项经常被作为数组发送。一些限制也允许你发送“缺省“选项到限制,以代替数组。在下面Choice限制的例子中,choices选项就是通过这一方式指定的:

  1. # Acme/BlogBundle/Resources/config/validation.yml 
  2. Acme\BlogBundle\Author: 
  3.     properties: 
  4.         gender: 
  5.             - Choice: [male, female] 

确保不要让指定选项的两个不同方法搞乱你。如果你不确定,检查限制的API文档或者总是发送选项数组(如上面第1种方法显示的那样),至少它是安全的。

限制的对象

限制可以被应用于一个类属性或一个公共的getter方法(如getFullName)。

属性

验证类属性是最基础的验证技巧。Symfony2允许你验证私有、保护和公共的属性。下面将向你展示如何配置Author类的$firstName和$lastName属性至少3个字符。

  1. # Acme/BlogBundle/Resources/config/validation.yml 
  2. Acme\BlogBundle\Author: 
  3.     properties: 
  4.         firstName: 
  5.             - NotBlank: ~ 
  6.             - MinLength: 3 
  7.         lastName: 
  8.             - NotBlank: ~ 
  9.             - MinLength: 3 

Getters

限制也可以应用在返回值的方法上。Symfony2允许你添加限制到任何名字中有着"get"或"is"的公共方法中。在本向导中,这两种类型的方法都被称为"getters“.

这种技巧的好处在于它允许你动态地验证你的对象。根据你对象的状态,方法返回不同值,然后验证。

下面将向你展示如何使用True限制去验证动态生成的令牌是否正确:

  1. # Acme/BlogBundle/Resources/config/validation.yml 
  2. Acme\BlogBundle\Author: 
  3.     getters: 
  4.         tokenValid: 
  5.             - True: { message: "The token is invalid" } 

 

公共的isTokenValid方法将执行一些逻辑去决定内部令牌是否合法,并返回true或false。

眼尖的你已经注意到getter的前缀("get"或"is")在映射中被忽略。这允许你将限制移到一个有着相同名字的属性(反之亦然),而无需改变你的验证逻辑。

最后一点

Symfony2验证器是一个强大的工具,它可以用来保证任何对象数据的“有效性”。验证背后的力量是“限制“,这是规则,你可以将其应用在属性或你对象的getter方法上。而你使用最常用的验证框架来间接地使用表单时,请记住,它可以在任何地方去验证任何对象。