模型验证¶
概览¶
Phalcon\Mvc\Model提供了多个事件来验证数据并实现业务规则。
<?php
namespace MyApp\Models;
use Phalcon\Mvc\Model;
use Phalcon\Filter\Validation;
use Phalcon\Filter\Validation\Validator\Uniqueness;
class Customers extends Model
{
    public function validation()
    {
        $validator = new Validation();
        $validator->add(
            'cst_email',
            new Uniqueness(
                [
                    'message' => 'The customer email must be unique',
                ]
            )
        );
        return $this->validate($validator);
    }
}
数据完整性¶
数据完整性在每个应用程序中都至关重要。你可以在模型中实现验证器,引入另一层验证,以确保存储到数据库中的数据符合你的业务规则。
特殊的validation事件允许我们在记录上调用内置验证器。Phalcon 在此验证阶段暴露了额外的内置验证器。所有可用的验证器都在Phalcon\Validation命名空间下。
<?php
namespace MyApp\Models;
use Phalcon\Mvc\Model;
use Phalcon\Filter\Validation;
use Phalcon\Filter\Validation\Validator\Uniqueness;
use Phalcon\Filter\Validation\Validator\InclusionIn;
class Invoices extends Model
{
    public function validation()
    {
        $validator = new Validation();
        $validator->add(
            'inv_status_flag',
            new InclusionIn(
                [
                    'domain'  => [
                        'Paid',
                        'Unpaid',
                    ],
                    'message' => 'The invoice must be ' .
                                 'either paid or unpaid',
                ]
            )
        );
        $validator->add(
            'inv_number',
            new Uniqueness(
                [
                    'message' => 'The invoice number must be unique',
                ]
            )
        );
        return $this->validate($validator);
    }
}
上述示例使用内置验证器Phalcon\Filter\Validation\Validator\InclusionIn进行验证。它检查字段inv_status_flag的值是否在一个域名列表中。如果该值未包含在此方法中,则验证器将失败并返回false.
注意
若要了解有关验证器的更多信息,请参阅验证文档
消息¶
Phalcon\Mvc\Model使用Phalcon\Messages\Messages集合来存储验证过程中生成的任何验证消息。
每条消息都是Phalcon\Messages\Message的实例,生成的消息集合可以通过getMessages()方法检索。每条消息提供了额外的信息,例如生成该消息的字段名称或消息类型:
<?php
if (false === $invoice->save()) {
    $messages = $invoice->getMessages();
    foreach ($messages as $message) {
        echo 'Message: ', $message->getMessage();
        echo 'Field: ', $message->getField();
        echo 'Type: ', $message->getType();
    }
}
Phalcon\Mvc\Model可以生成以下类型的验证消息:
| 类型 | 生成时 | 
|---|---|
ConstraintViolation |  字段是虚拟外键的一部分,尝试插入/更新一个在引用模型中不存在的值 | 
InvalidCreateAttempt |  尝试创建已经存在的记录 | 
InvalidUpdateAttempt |  尝试更新不存在的记录 | 
InvalidValue |  验证器因无效值而失败 | 
PresenceOf |  数据库中具有非null属性的字段尝试插入/更新一个null值 |  
The getMessages()方法可以在模型中被重写,以替换/翻译 ORM 自动生成的默认消息:
<?php
namespace MyApp\Models;
use Phalcon\Mvc\Model;
class Invoices extends Model
{
    public function getMessages()
    {
        $messages = [];
        foreach (parent::getMessages() as $message) {
            switch ($message->getType()) {
                case 'InvalidCreateAttempt':
                    $messages[] = 'The record cannot be created '
                                . 'because it already exists';
                    break;
                case 'InvalidUpdateAttempt':
                    $messages[] = "The record cannot be updated '
                                . 'because it doesn't exist";
                    break;
                case 'PresenceOf':
                    $messages[] = 'The field ' 
                                . $message->getField() 
                                . ' is mandatory';
                    break;
            }
        }
        return $messages;
    }
}
验证失败事件¶
当数据验证过程发现任何不一致时,会有其他可用事件:
| 操作 | 名称 | 解释 | 
|---|---|---|
| 插入或更新 | notSaved |  触发当INSERT或UPDATE操作由于任何原因失败时 |  
| 插入、删除或更新 | onValidationFails |  触发当任何数据操作失败时 | 
自定义¶
The 验证文档详细说明了如何创建自己的验证器。你可以使用这些验证器并在多个模型中复用它们。一个验证器也可以简单如:
<?php
namespace MyApp\Models;
use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Message;
class Invoices extends Model
{
    public function validation()
    {
        if ('Unpaid' === $this->inv_type_flag) {
            $message = new Message(
                'Unpaid invoices are not allowed',
                'inv_type_flag',
                'UnpaidInvoiceType'
            );
            $this->appendMessage($message);
            return false;
        }
        return true;
    }
}