/**
* 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. Thread start()方法和run()方法的区别

    转自:http://www.cnblogs.com/skywang12345/p/3479083.html start():作用一个新的线程,新线程会执行相应的run()方法,start()不能被重复 ...

  2. Hibernate性能优化之SessionFactory重用

    Hibernate优化的方式有很多,如缓存.延迟加载以及与SQL合理映射,通过对SessionFactory使用的优化是最基础的. SessionFactory负责创建Session实例,Sessio ...

  3. js 添加事件兼容性

    var tools = { //添加事件 addHandle: function (e, type, handle) { if (e.addEventListener) { e.addEventLis ...

  4. Milk Patterns POJ - 3261(后缀数组+二分)

    题意: 求可重叠的最长重复子串,但有一个限制条件..要至少重复k次 解析: 二分枚举k,对于连续的height 如果height[i] >= k 说明它们至少有k个元素是重复的,所以判断一下就好 ...

  5. Day22-Django之信号

    1. 如果往数据库中增加数据的时候,希望生成一个日志.在数据保存之前以及保存之后. Django中提供了“信号调度”,用于在框架执行操作时解耦.通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去 ...

  6. c++11 左值引用、右值引用

    c++11 左值引用.右值引用 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #i ...

  7. 【刷题】BZOJ 4817 [Sdoi2017]树点涂色

    Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...

  8. 【spring】- springmvc 工作原理

    原理 本质是将DispatcherServlet及关联的Spring上下文环境的初始化工作织入Servlet的生命周期内,将外部WEB请求转换为Spring Bean能处理的形式,然后将处理后的结果借 ...

  9. 51nod 1681 公共祖先 | 树状数组

    51nod 1681 公共祖先 有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完 ...

  10. 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!(dij+bitset)

    从S出发跑dij,从T出发跑dij,顺便最短路计数. 令$F(x)$为$S$到$T$最短路经过$x$的方案数,显然这个是可以用$S$到$x$的方案数乘$T$到$x$的方案数来得到. 然后第一个条件就变 ...