验证Validation

Phalcon\Validation对Phalcon来说是一个相对独立的组件,它可以对任意的数据进行验证。 当然也可以用来对非模型内的数据进行验证。 下面的例子展示了一些基本的使用方法:

Phalcon\Validation is an independent validation component that validates an arbitrary set of data. This component can be used to implement validation rules on data objects that do not belong to a model or collection.

The following example shows its basic usage:

  1. <?php
  2. use Phalcon\Validation;
  3. use Phalcon\Validation\Validator\Email;
  4. use Phalcon\Validation\Validator\PresenceOf;
  5. $validation = new Validation();
  6. $validation->add('name', new PresenceOf(array(
  7. 'message' => 'The name is required'
  8. )));
  9. $validation->add('email', new PresenceOf(array(
  10. 'message' => 'The e-mail is required'
  11. )));
  12. $validation->add('email', new Email(array(
  13. 'message' => 'The e-mail is not valid'
  14. )));
  15. $messages = $validation->validate($_POST);
  16. if (count($messages)) {
  17. foreach ($messages as $message) {
  18. echo $message, '<br>';
  19. }
  20. }

由于此模型是松耦合设计的,故此我们也可以使用自己书写的验证工具:

The loosely-coupled design of this component allows you to create your own validators along with the ones provided by the framework.

初始化验证Initializing Validation

我们可以直接在Phalcon\Validation初始化时添加验证链。我们可以把验证器放在一个单独的文件中以提高代码的重用率及可组织性:

Validation chains can be initialized in a direct manner by just adding validators to the Phalcon\Validation object. You can put your validations in a separate file for better re-use code and organization:

  1. <?php
  2. use Phalcon\Validation;
  3. use Phalcon\Validation\Validator\Email;
  4. use Phalcon\Validation\Validator\PresenceOf;
  5. class MyValidation extends Validation
  6. {
  7. public function initialize()
  8. {
  9. $this->add('name', new PresenceOf(array(
  10. 'message' => 'The name is required'
  11. )));
  12. $this->add('email', new PresenceOf(array(
  13. 'message' => 'The e-mail is required'
  14. )));
  15. $this->add('email', new Email(array(
  16. 'message' => 'The e-mail is not valid'
  17. )));
  18. }
  19. }

然后初始化并使用自己的验证器:

Then initialize and use your own validator:

  1. <?php
  2. $validation = new MyValidation();
  3. $messages = $validation->validate($_POST);
  4. if (count($messages)) {
  5. foreach ($messages as $message) {
  6. echo $message, '<br>';
  7. }
  8. }

验证器Validators

Phalcon的验证组件中内置了一些验证器:

Phalcon exposes a set of built-in validators for this component:

NameExplanationExample
PresenceOfValidates that a field’s value is not null or empty string.Example
IdenticalValidates that a field’s value is the same as a specified valueExample
EmailValidates that field contains a valid email formatExample
ExclusionInValidates that a value is not within a list of possible valuesExample
InclusionInValidates that a value is within a list of possible valuesExample
RegexValidates that the value of a field matches a regular expressionExample
StringLengthValidates the length of a stringExample
BetweenValidates that a value is between two valuesExample
ConfirmationValidates that a value is the same as another present in the dataExample
UrlValidates that field contains a valid URLExample

下面代码演示了如何为这个组件创建额外的验证器:

The following example explains how to create additional validators for this component:

  1. <?php
  2. use Phalcon\Validation\Message;
  3. use Phalcon\Validation\Validator;
  4. use Phalcon\Validation\ValidatorInterface;
  5. class IpValidator extends Validator implements ValidatorInterface
  6. {
  7. /**
  8. * Executes the validation
  9. *
  10. * @param Phalcon\Validation $validator
  11. * @param string $attribute
  12. * @return boolean
  13. */
  14. public function validate($validator, $attribute)
  15. {
  16. $value = $validator->getValue($attribute);
  17. if (!filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
  18. $message = $this->getOption('message');
  19. if (!$message) {
  20. $message = 'The IP is not valid';
  21. }
  22. $validator->appendMessage(new Message($message, $attribute, 'Ip'));
  23. return false;
  24. }
  25. return true;
  26. }
  27. }

最重要的一点即是难证器要返回一个布尔值以标识验证是否成功:

It is important that validators return a valid boolean value indicating if the validation was successful or not.

验证信息Validation Messages

Phalcon\Validation 内置了一个消息子系统,这提供了一个非常好的验证消息回传机制,以便在验证结束后取得验证信息,比如失败原因等。每个消息由一个 :doc:`Phalcon\Validation\Message <../api/Phalcon_Mvc_Model_Message>`类的实例构成。验证过程产生的消息可以使用getMessages()方法取得。 每条消息都有一些扩展的信息组成比如产生错误的属性或消息的类型等:

Phalcon\Validation has a messaging subsystem that provides a flexible way to output or store the validation messages generated during the validation processes.

Each message consists of an instance of the class Phalcon\Validation\Message. The set of messages generated can be retrieved with the getMessages() method. Each message provides extended information like the attribute that generated the message or the message type:

  1. <?php
  2. $messages = $validation->validate();
  3. if (count($messages)) {
  4. foreach ($validation->getMessages() as $message) {
  5. echo "Message: ", $message->getMessage(), "\n";
  6. echo "Field: ", $message->getField(), "\n";
  7. echo "Type: ", $message->getType(), "\n";
  8. }
  9. }

当然这里我们也可以对getMessages()方法进行重写, 以取得我们想要的信息:

The getMessages() method can be overridden in a validation class to replace/translate the default messages generated by the validators:

  1. <?php
  2. use Phalcon\Validation;
  3. class MyValidation extends Validation
  4. {
  5. public function initialize()
  6. {
  7. // ...
  8. }
  9. public function getMessages()
  10. {
  11. $messages = array();
  12. foreach (parent::getMessages() as $message) {
  13. switch ($message->getType()) {
  14. case 'PresenceOf':
  15. $messages[] = 'The field ' . $message->getField() . ' is mandatory';
  16. break;
  17. }
  18. }
  19. return $messages;
  20. }
  21. }

或我们也可以传送一个message参数以覆盖验证器中默认的信息:

Or you can pass a ‘message’ parameter to change the default message in each validator:

  1. <?php
  2. use Phalcon\Validation\Validator\Email;
  3. $validation->add('email', new Email(array(
  4. 'message' => 'The e-mail is not valid'
  5. )));

默认,getMessages()方法会返回在验证过程中所产生的信息。 我们可以使用filter()方法来过滤我们感兴趣的消息:

By default, ‘getMessages’ returns all the messages generated during validation. You can filter messages for a specific field using the ‘filter’ method:

  1. <?php
  2. $messages = $validation->validate();
  3. if (count($messages)) {
  4. //Filter only the messages generated for the field 'name'
  5. foreach ($validation->getMessages()->filter('name') as $message) {
  6. echo $message;
  7. }
  8. }

过滤数据Filtering of Data

我们可以在数据被验证之前对其先进行过滤,以确保那些恶意的或不正确的数据不被验证。

Data can be filtered prior to the validation ensuring that malicious or incorrect data is not validated.

  1. <?php
  2. use Phalcon\Validation;
  3. $validation = new Validation();
  4. $validation
  5. ->add('name', new PresenceOf(array(
  6. 'message' => 'The name is required'
  7. )))
  8. ->add('email', new PresenceOf(array(
  9. 'message' => 'The email is required'
  10. )));
  11. //Filter any extra space
  12. $validation->setFilters('name', 'trim');
  13. $validation->setFilters('email', 'trim');

这里我们使用 filter: 组件进行过滤。 我们还可以使用自定义的或内置的过滤器。

Filtering and sanitizing is performed using the filter: component. You can add more filters to this component or use the built-in ones.

验证事件Validation Events

当在类中执行验证时, 我们可以在beforeValidation或afterValidation方法(事件)中执行额外的检查,过滤,清理等工作。 如果beforeValidation方法返回了false 则验证会被中止:

When validations are organized in classes, you can implement the ‘beforeValidation’ and ‘afterValidation’ methods to perform additional checks, filters, clean-up, etc. If ‘beforeValidation’ method returns false the validation is automatically cancelled:

  1. <?php
  2. use Phalcon\Validation;
  3. class LoginValidation extends Validation
  4. {
  5. public function initialize()
  6. {
  7. // ...
  8. }
  9. /**
  10. * Executed before validation
  11. *
  12. * @param array $data
  13. * @param object $entity
  14. * @param Phalcon\Validation\Message\Group $messages
  15. * @return bool
  16. */
  17. public function beforeValidation($data, $entity, $messages)
  18. {
  19. if ($this->request->getHttpHost() != 'admin.mydomain.com') {
  20. $messages->appendMessage(new Message('Only users can log on in the administration domain'));
  21. return false;
  22. }
  23. return true;
  24. }
  25. /**
  26. * Executed after validation
  27. *
  28. * @param array $data
  29. * @param object $entity
  30. * @param Phalcon\Validation\Message\Group $messages
  31. */
  32. public function afterValidation($data, $entity, $messages)
  33. {
  34. //... add additional messages or perform more validations
  35. }
  36. }

取消验证Cancelling Validations

默认所有的验证器都会被执行,不管验证成功与否。 我们可以通过设置 cancelOnFail 参数为 true 来指定某个验证器验证失败时中止以后的所有验证:

By default all validators assigned to a field are tested regardless if one of them have failed or not. You can change this behavior by telling the validation component which validator may stop the validation:

  1. <?php
  2. use Phalcon\Validation;
  3. use Phalcon\Validation\Validator\Regex;
  4. use Phalcon\Validation\Validator\PresenceOf;
  5. $validation = new Validation();
  6. $validation
  7. ->add('telephone', new PresenceOf(array(
  8. 'message' => 'The telephone is required',
  9. 'cancelOnFail' => true
  10. )))
  11. ->add('telephone', new Regex(array(
  12. 'message' => 'The telephone is required',
  13. 'pattern' => '/\+44 [0-9]+/'
  14. )))
  15. ->add('telephone', new StringLength(array(
  16. 'messageMinimum' => 'The telephone is too short',
  17. 'min' => 2
  18. )));

第一个验证器中 cancelOnFail 参数设置为 true 则表示如果此验证器验证失败则验证链中接下的验证不会被执行。

The first validator has the option ‘cancelOnFail’ with a value of true, therefore if that validator fails the remaining validators in the chain are not executed.

我们可以在自定义的验证器中设置 cancelOnFail 为 true 来停止验证链:

If you are creating custom validators you can dynamically stop the validation chain by setting the ‘cancelOnFail’ option:

  1. <?php
  2. use Phalcon\Validation\Message;
  3. use Phalcon\Validation\Validator;
  4. use Phalcon\Validation\ValidatorInterface;
  5. class MyValidator extends Validator implements ValidatorInterface
  6. {
  7. /**
  8. * Executes the validation
  9. *
  10. * @param Phalcon\Validation $validator
  11. * @param string $attribute
  12. * @return boolean
  13. */
  14. public function validate($validator, $attribute)
  15. {
  16. // If the attribute value is name we must stop the chain
  17. if ($attribute == 'name') {
  18. $validator->setOption('cancelOnFail', true);
  19. }
  20. //...
  21. }
  22. }