/**
* Validates the specified object.
* @param \yii\base\Model $model the data model being validated
* @param array|null $attributes the list of attributes to be validated.
* Note that if an attribute is not associated with the validator - it will be
* ignored. If this parameter is null, every attribute listed in [[attributes]] will be validated.
*/
public function validateAttributes($model, $attributes = null)
{
//传入的是被验证的属性。属性很可能是某一具体场景下的需验证属性
//这里进行验证器过滤,必须同时在场景中和验证器中都有,才会接着去验证。
if (is_array($attributes)) {
$newAttributes = [];
foreach ($attributes as $attribute) {
if (in_array($attribute, $this->getAttributeNames(), true)) {
$newAttributes[] = $attribute;
}
}
$attributes = $newAttributes;
} else {
$attributes = $this->getAttributeNames();
} foreach ($attributes as $attribute) {
$skip = $this->skipOnError && $model->hasErrors($attribute)
|| $this->skipOnEmpty && $this->isEmpty($model->$attribute);
         //可以肯定的是在一般场景下$skip就是false,因此下面的判断是会执行的,而$this->when是rules里传入的回调,一般没使用这个回调,因此为null,
         //继续执行$this->validateAttribute($model, $attribute);
             if (!$skip) {
//此处when默认为null,也即用户在验证规则里没设置。继续下一步
if ($this->when === null || call_user_func($this->when, $model, $attribute)) {
$this->validateAttribute($model, $attribute);
}
}
}
}

这个验证指定对象的验证器在(一)介绍过了,这里贴一下代码。继续执行$this->validateAttribute($model, $attribute);代码如下:

 /**
* Validates a single attribute.
* Child classes must implement this method to provide the actual validation logic.
* @param \yii\base\Model $model the data model to be validated
* @param string $attribute the name of the attribute to be validated.
*/
public function validateAttribute($model, $attribute)
{
$result = $this->validateValue($model->$attribute);
if (!empty($result)) {
$this->addError($model, $attribute, $result[0], $result[1]);
}
}

验证一个单独属性,子类必须集成这个方法来提供实际的验证逻辑,$model是被验证的model,$attribute是被验证的属性。哦,原来是在这添加的错误,执行完后,validate方法会返回这个错误状态,有错或无错。进这个validateValue方法看一下。

 /**
* Validates a value.
* A validator class can implement this method to support data validation out of the context of a data model.
* @param mixed $value the data value to be validated.
* @return array|null the error message and the parameters to be inserted into the error message.
* Null should be returned if the data is valid.
* @throws NotSupportedException if the validator does not supporting data validation without a model
*/
protected function validateValue($value)
{
throw new NotSupportedException(get_class($this) . ' does not support validateValue().');
}

这个方法是个虚拟方法,不能直接被调用,必须在子类中实现该方法用以支持数据模型上下文的验证。$value是被验证的值,返回的错误信息,参数会插入错误信息,null返回代表数据不可用。如果验证器不支持数据验证模型将抛出错误。

咱们以required验证器为例:

 <?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/ namespace yii\validators; use Yii; /**
* RequiredValidator validates that the specified attribute does not have null or empty value.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class RequiredValidator extends Validator
{
/**
* @var bool whether to skip this validator if the value being validated is empty.
*/
public $skipOnEmpty = false;
/**
* @var mixed the desired value that the attribute must have.
* If this is null, the validator will validate that the specified attribute is not empty.
* If this is set as a value that is not null, the validator will validate that
* the attribute has a value that is the same as this property value.
* Defaults to null.
* @see strict
*/
public $requiredValue;
/**
* @var bool whether the comparison between the attribute value and [[requiredValue]] is strict.
* When this is true, both the values and types must match.
* Defaults to false, meaning only the values need to match.
* Note that when [[requiredValue]] is null, if this property is true, the validator will check
* if the attribute value is null; If this property is false, the validator will call [[isEmpty]]
* to check if the attribute value is empty.
*/
public $strict = false;
/**
* @var string the user-defined error message. It may contain the following placeholders which
* will be replaced accordingly by the validator:
*
* - `{attribute}`: the label of the attribute being validated
* - `{value}`: the value of the attribute being validated
* - `{requiredValue}`: the value of [[requiredValue]]
*/
public $message; /**
* @inheritdoc
*/
public function init()
{
parent::init();
if ($this->message === null) {
$this->message = $this->requiredValue === null ? Yii::t('yii', '{attribute} cannot be blank.')
: Yii::t('yii', '{attribute} must be "{requiredValue}".');
}
} /**
* @inheritdoc
*/
protected function validateValue($value)
{
if ($this->requiredValue === null) {
if ($this->strict && $value !== null || !$this->strict && !$this->isEmpty(is_string($value) ? trim($value) : $value)) {
return null;
}
} elseif (!$this->strict && $value == $this->requiredValue || $this->strict && $value === $this->requiredValue) {
return null;
}
if ($this->requiredValue === null) {
return [$this->message, []];
} else {
return [$this->message, [
'requiredValue' => $this->requiredValue,
]];
}
} /**
* @inheritdoc
*/
public function clientValidateAttribute($model, $attribute, $view)
{
ValidationAsset::register($view);
$options = $this->getClientOptions($model, $attribute); return 'yii.validation.required(value, messages, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ');';
} /**
* @inheritdoc
*/
public function getClientOptions($model, $attribute)
{
$options = [];
if ($this->requiredValue !== null) {
$options['message'] = $this->formatMessage($this->message, [
'requiredValue' => $this->requiredValue,
]);
$options['requiredValue'] = $this->requiredValue;
} else {
$options['message'] = $this->message;
}
if ($this->strict) {
$options['strict'] = 1;
} $options['message'] = $this->formatMessage($options['message'], [
'attribute' => $model->getAttributeLabel($attribute),
]); return $options;
}
}

这个验证器用于验证非空非null属性。$skipOnEmpty,此时这个值设置为false,而不是基类validator上的true,也就是不跳过空值。$requiredValue是属性必须有的期待值,如果为null,验证器将验证指定的属性是否为空。如果不为空,那就验证跟该值指定的属性同名的属性。默认是null。$strict用来指定$requiredValue给定属性值跟传入属性值是否完全相同,如果为真,类型和值必须都相同。默认为假,只检查值,注意当requiredValue为null,如果这个属性为真,验证器将检查属性值是否为null,如果属性为false,验证器就会调用isEmpty检查属性值是否为空。$message是用户定义的错误信息,如果包含下面的占位符将根据规则进行替换。

* - `{attribute}`: the label of the attribute being validated

* - `{value}`: the value of the attribute being validated

* - `{requiredValue}`: the value of [[requiredValue]]

第一个被验证的属性标签,第二个被验证属性值,第三个被验证的requiredValue的值。

yii验证系统学习记录,基于yiicms(二)的更多相关文章

  1. yii验证系统学习记录,基于yiicms(一)写的太长了,再写一篇(二)

    项目地址:https://gitee.com/templi/yiicms 感谢七觞酒大神的付出,和免费分享.当然也感谢yii2的开发团队们. 项目已经安全完毕,不知道后台密码,这种背景下,后台无法进去 ...

  2. 系统学习 Java IO (十二)----数据流和对象流

    目录:系统学习 Java IO---- 目录,概览 DataInputStream/DataOutputStream 允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型. 要想使用 ...

  3. 基于OpenCv的人脸检测、识别系统学习制作笔记之二

    在网上找到了一个博客,里面有大量内容适合初学者接触和了解人脸检测的博文,正好符合我目前的学习方面,故将链接放上来,后续将分类原博客的博文并加上学习笔记. 传送门: http://blog.sina.c ...

  4. JavaScript个人学习记录总结(二)——验证表单输入之模式匹配

    该示例检查从文本窗口部件中获取姓名和电话号码这两个表单数据的有效性.当文本框中的值发生变化时,即引发一个change事件,从而可以调用一个函数来检查这两个输入值的格式是否正确. validator.h ...

  5. JavaWeb学习记录(十二)——商城购物之数据库操作的接口定义

    一.基本接口,该项目中所有接口都继承它 package blank.dao; import java.util.List; public interface BaseDao<T,PK> { ...

  6. PackageManagerService 学习记录 基于7.1.1源码

    参考: http://blog.csdn.net/innost/article/details/47253179 http://blog.csdn.net/gaugamela/article/deta ...

  7. AM335X的SD卡更新系统学习记录

    一般利用一张SD卡就能进行系统的更新,以前一直不知是什么原理,最近了解了下,对了解到的内容做个记录.使用的是AM335X平台,系统是Linux,文件系统是EXT3: 1.首先需要一张分好分区的SD卡( ...

  8. 个人学习记录1:二维数组保存到cookie后再读取

    二维数组保存到cookie后再读取 var heartsArray = [[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0],[0,0, ...

  9. PHP实战-文章发布系统学习记录

    跟随大师的步伐,一步一步向前行进,PHP学习之路中的历程. 如果图片不能正常查看请访问云笔记链接 http://note.youdao.com/share/?id=3c25d8c03ef946d9c6 ...

随机推荐

  1. 基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程

    许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的 ...

  2. Redis:主从复制

    前言 在前面的两篇文章中,分别介绍了Redis的内存模型和Redis的持久化. 在Redis的持久化中曾提到,Redis高可用的方案包括持久化.主从复制(及读写分离).哨兵和集群.其中持久化侧重解决的 ...

  3. 【.Net】c# 让double保留两位小数

    1.Math.Round(0.333333,2);//按照四舍五入的国际标准2.    double dbdata=0.335333;    string str1=String.Format(&qu ...

  4. Spring、SpringMVC、MyBatis整合

    项目结构: 新建web项目:File->new->Dynamic Web Project 一.准备所需jar包1. Spring框架的jar包 spring-framework-5.0.4 ...

  5. jsp中的下载链接

    1.下载链接jsp界面(a链接直接链文件可以看出文件在服务器中的路径,用servlet处理的链接则看不出) <%@ page language="java" contentT ...

  6. [提升性选讲] 树形DP进阶:一类非线性的树形DP问题(例题 BZOJ4403 BZOJ3167)

    转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7337179.html 树形DP是一种在树上进行的DP相对比较难的DP题型.由于状态的定义多种多样,因此解法也五 ...

  7. hdu1542 Atlantis (线段树+矩阵面积并+离散化)

    There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...

  8. Day22-中间件

    1.中间件,在其它程序中,有的叫管道,有的叫http handler.下面是原生的中间件 2.自己也可以写中间件 2.1 写中间件,新建文件夹Middle,新建m1.py 2.2 在setting里注 ...

  9. 【BZOJ2423】最长公共子序列(动态规划)

    [BZOJ2423]最长公共子序列(动态规划) 题面 BZOJ 洛谷 题解 今天考试的时候,神仙出题人\(fdf\)把这道题目作为一个二合一出了出来,我除了orz还是只会orz. 对于如何\(O(n^ ...

  10. Longest Word in Dictionary through Deleting - LeetCode

    目录 题目链接 注意点 解法 小结 题目链接 Longest Word in Dictionary through Deleting - LeetCode 注意点 长度一样的字符串要按字典序返回较小的 ...