💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] # 验证 `Phalcon\Validation` 是一个独立的验证组件,用于验证任意数据集。此组件可用于对不属于模型或集合的数据对象实现验证规则。 以下示例显示了其基本用法: ```php <?php use Phalcon\Validation; use Phalcon\Validation\Validator\Email; use Phalcon\Validation\Validator\PresenceOf; $validation = new Validation(); $validation->add( 'name', new PresenceOf( [ 'message' => 'The name is required', ] ) ); $validation->add( 'email', new PresenceOf( [ 'message' => 'The e-mail is required', ] ) ); $validation->add( 'email', new Email( [ 'message' => 'The e-mail is not valid', ] ) ); $messages = $validation->validate($_POST); if (count($messages)) { foreach ($messages as $message) { echo $message, '<br>'; } } ``` 此组件的松耦合设计允许您以框架提供的验证器创建自己的验证器。 ## 初始化验证 只需在`Phalcon\Validation`对象中添加验证器,即可直接初始化验证链。您可以将验证放在单独的文件中,以便更好地重用代码和组织: ```php <?php use Phalcon\Validation; use Phalcon\Validation\Validator\Email; use Phalcon\Validation\Validator\PresenceOf; class MyValidation extends Validation { public function initialize() { $this->add( 'name', new PresenceOf( [ 'message' => 'The name is required', ] ) ); $this->add( 'email', new PresenceOf( [ 'message' => 'The e-mail is required', ] ) ); $this->add( 'email', new Email( [ 'message' => 'The e-mail is not valid', ] ) ); } } ``` 然后初始化并使用您自己的验证器: ```php <?php $validation = new MyValidation(); $messages = $validation->validate($_POST); if (count($messages)) { foreach ($messages as $message) { echo $message, '<br>'; } } ``` ## 验证器 Phalcon为此组件公开了一组内置验证器: | 类 | 说明 | | ---------------------------------------------- | ------------------------------------------------------------------ | | `Phalcon\Validation\Validator\Alnum` | 验证字段的值仅为字母数字字符。 | | `Phalcon\Validation\Validator\Alpha` | 验证字段的值是否仅为字母字符。 | | `Phalcon\Validation\Validator\Date` | 验证字段的值是否为有效日期。 | | `Phalcon\Validation\Validator\Digit` | 验证字段的值是否只是数字字符。 | | `Phalcon\Validation\Validator\File` | 验证字段的值是否是正确的文件。 | | `Phalcon\Validation\Validator\Uniqueness` | 验证字段的值在相关模型中是唯一的。 | | `Phalcon\Validation\Validator\Numericality` | 验证字段的值是否为有效数值。 | | `Phalcon\Validation\Validator\PresenceOf` | 验证字段的值不为null或空字符串。 | | `Phalcon\Validation\Validator\Identical` | 验证字段的值是否与指定值相同。 | | `Phalcon\Validation\Validator\Email` | 验证该字段是否包含有效的电子邮件格式。 | | `Phalcon\Validation\Validator\ExclusionIn` | 验证值是否不在可能值列表中。 | | `Phalcon\Validation\Validator\InclusionIn` | 验证值是否在可能值列表中。 | | `Phalcon\Validation\Validator\Regex` | 验证字段的值是否与正则表达式匹配。 | | `Phalcon\Validation\Validator\StringLength` | 验证字符串的长度。 | | `Phalcon\Validation\Validator\Between` | 验证值是否在两个值之间。 | | `Phalcon\Validation\Validator\Confirmation` | 验证值与数据中存在的另一个值相同。 | | `Phalcon\Validation\Validator\Url` | 验证该字段是否包含有效的URL。 | | `Phalcon\Validation\Validator\CreditCard` | 验证信用卡号。 | | `Phalcon\Validation\Validator\Callback` | 使用回调函数进行验证。 | 以下示例说明如何为此组件创建其他验证器: ```php <?php use Phalcon\Validation; use Phalcon\Validation\Message; use Phalcon\Validation\Validator; class IpValidator extends Validator { /** * Executes the validation * * @param Validation $validator * @param string $attribute * @return boolean */ public function validate(Validation $validator, $attribute) { $value = $validator->getValue($attribute); if (!filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) { $message = $this->getOption('message'); if (!$message) { $message = 'The IP is not valid'; } $validator->appendMessage( new Message($message, $attribute, 'Ip') ); return false; } return true; } } ``` 验证器返回有效的布尔值非常重要,该值指示验证是否成功。 ## 回调验证器 通过使用`Phalcon\Validation\Validator\Callback`,您可以执行自定义函数,该函数必须返回将用于验证同一字段的布尔值或新验证器类。通过返回真正的验证将成功,返回`false`将意味着验证失败。执行此验证程序时,Phalcon将根据数据传递数据 - 如果它是实体,则将传递实体,否则传递数据。有例子: ```php <?php use \Phalcon\Validation; use \Phalcon\Validation\Validator\Callback; use \Phalcon\Validation\Validator\PresenceOf; $validation = new Validation(); $validation->add( 'amount', new Callback( [ 'callback' => function($data) { return $data['amount'] % 2 == 0; }, 'message' => 'Only even number of products are accepted' ] ) ); $validation->add( 'amount', new Callback( [ 'callback' => function($data) { if($data['amount'] % 2 == 0) { return $data['amount'] != 2; } return true; }, 'message' => "You can't buy 2 products" ] ) ); $validation->add( 'description', new Callback( [ 'callback' => function($data) { if($data['amount'] >= 10) { return new PresenceOf( [ 'message' => 'You must write why you need so big amount.' ] ); } return true; } ] ) ); $messages = $validation->validate(['amount' => 1]); // will return message from first validator $messages = $validation->validate(['amount' => 2]); // will return message from second validator $messages = $validation->validate(['amount' => 10]); // will return message from validator returned by third validator ``` ## 验证消息 `Phalcon\Validation` 有一个消息传递子系统,它提供了一种灵活的方法来输出或存储验证过程中生成的验证消息。 每条消息都包含`Phalcon\Validation\Message`类的实例。可以使用`getMessages()`方法获取生成的消息集。每条消息都提供扩展信息,例如生成消息的属性或消息类型: ```php <?php $messages = $validation->validate(); if (count($messages)) { foreach ($messages as $message) { echo 'Message: ', $message->getMessage(), "\n"; echo 'Field: ', $message->getField(), "\n"; echo 'Type: ', $message->getType(), "\n"; } } ``` 您可以传递`message`参数来更改/转换每个验证器中的默认消息,即使可以使用消息中的通配符`:field`替换为字段的标签: ```php <?php use Phalcon\Validation\Validator\Email; $validation->add( 'email', new Email( [ 'message' => 'The e-mail is not valid', ] ) ); ``` 默认情况下, `getMessages()` 方法返回验证期间生成的所有消息。您可以使用`filter()`方法过滤特定字段的消息: ```php <?php $messages = $validation->validate(); if (count($messages)) { // Filter only the messages generated for the field 'name' $filteredMessages = $messages->filter('name'); foreach ($filteredMessages as $message) { echo $message; } } ``` ## 过滤数据 可以在验证之前过滤数据,确保未验证恶意或不正确的数据。 ```php <?php use Phalcon\Validation; $validation = new Validation(); $validation->add( 'name', new PresenceOf( [ 'message' => 'The name is required', ] ) ); $validation->add( 'email', new PresenceOf( [ 'message' => 'The email is required', ] ) ); // Filter any extra space $validation->setFilters('name', 'trim'); $validation->setFilters('email', 'trim'); ``` 使用过滤器组件进行过滤和消毒。您可以向此组件添加更多过滤器或使用内置过滤器。 ## 验证事件 在类中组织验证时,可以实现`beforeValidation()`和`afterValidation()`方法以执行其他检查,过滤,清理等。如果`beforeValidation()`方法返回`false`,则验证将自动取消: ```php <?php use Phalcon\Validation; class LoginValidation extends Validation { public function initialize() { // ... } /** * Executed before validation * * @param array $data * @param object $entity * @param Phalcon\Validation\Message\Group $messages * @return bool */ public function beforeValidation($data, $entity, $messages) { if ($this->request->getHttpHost() !== 'admin.mydomain.com') { $messages->appendMessage( new Message('Only users can log on in the administration domain') ); return false; } return true; } /** * Executed after validation * * @param array $data * @param object $entity * @param Phalcon\Validation\Message\Group $messages */ public function afterValidation($data, $entity, $messages) { // ... Add additional messages or perform more validations } } ``` ## 取消验证 默认情况下,将测试分配给某个字段的所有验证程序,无论其中一个验证程序是否已失败。您可以通过告知验证组件哪个验证程序可以停止验证来更改此行为: ```php <?php use Phalcon\Validation; use Phalcon\Validation\Validator\Regex; use Phalcon\Validation\Validator\PresenceOf; $validation = new Validation(); $validation->add( 'telephone', new PresenceOf( [ 'message' => 'The telephone is required', 'cancelOnFail' => true, ] ) ); $validation->add( 'telephone', new Regex( [ 'message' => 'The telephone is required', 'pattern' => '/\+44 [0-9]+/', ] ) ); $validation->add( 'telephone', new StringLength( [ 'messageMinimum' => 'The telephone is too short', 'min' => 2, ] ) ); ``` 第一个验证器具有选项`cancelOnFail`,其值为`true`,因此如果该验证器失败,则不会执行链中的其余验证器。 如果要创建自定义验证器,可以通过设置`cancelOnFail`选项动态停止验证链: ```php <?php use Phalcon\Validation; use Phalcon\Validation\Message; use Phalcon\Validation\Validator; class MyValidator extends Validator { /** * Executes the validation * * @param Phalcon\Validation $validator * @param string $attribute * @return boolean */ public function validate(Validation $validator, $attribute) { // If the attribute value is name we must stop the chain if ($attribute === 'name') { $validator->setOption('cancelOnFail', true); } // ... } } ``` ## 避免验证空值 您可以将选项`allowEmpty`传递给所有内置验证器,以避免在传递空值时执行验证: ```php <?php use Phalcon\Validation; use Phalcon\Validation\Validator\Regex; $validation = new Validation(); $validation->add( 'telephone', new Regex( [ 'message' => 'The telephone is required', 'pattern' => '/\+44 [0-9]+/', 'allowEmpty' => true, ] ) ); ``` ## 递归验证 您还可以通过`afterValidation()` 方法在另一个中运行`Validation`实例。在此示例中,验证`CompanyValidation`实例还将检查`PhoneValidation`实例: ```php <?php use Phalcon\Validation; class CompanyValidation extends Validation { /** * @var PhoneValidation */ protected $phoneValidation; public function initialize() { $this->phoneValidation = new PhoneValidation(); } public function afterValidation($data, $entity, $messages) { $phoneValidationMessages = $this->phoneValidation->validate( $data['phone'] ); $messages->appendMessages( $phoneValidationMessages ); } } ```