yii验证系统学习记录,基于yiicms(二)

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

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

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

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

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

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

咱们以required验证器为例:

  1 <?php
  2 /**
  3  * @link http://www.yiiframework.com/
  4  * @copyright Copyright (c) 2008 Yii Software LLC
  5  * @license http://www.yiiframework.com/license/
  6  */
  7 
  8 namespace yii\validators;
  9 
 10 use Yii;
 11 
 12 /**
 13  * RequiredValidator validates that the specified attribute does not have null or empty value.
 14  *
 15  * @author Qiang Xue <qiang.xue@gmail.com>
 16  * @since 2.0
 17  */
 18 class RequiredValidator extends Validator
 19 {
 20     /**
 21      * @var bool whether to skip this validator if the value being validated is empty.
 22      */
 23     public $skipOnEmpty = false;
 24     /**
 25      * @var mixed the desired value that the attribute must have.
 26      * If this is null, the validator will validate that the specified attribute is not empty.
 27      * If this is set as a value that is not null, the validator will validate that
 28      * the attribute has a value that is the same as this property value.
 29      * Defaults to null.
 30      * @see strict
 31      */
 32     public $requiredValue;
 33     /**
 34      * @var bool whether the comparison between the attribute value and [[requiredValue]] is strict.
 35      * When this is true, both the values and types must match.
 36      * Defaults to false, meaning only the values need to match.
 37      * Note that when [[requiredValue]] is null, if this property is true, the validator will check
 38      * if the attribute value is null; If this property is false, the validator will call [[isEmpty]]
 39      * to check if the attribute value is empty.
 40      */
 41     public $strict = false;
 42     /**
 43      * @var string the user-defined error message. It may contain the following placeholders which
 44      * will be replaced accordingly by the validator:
 45      *
 46      * - `{attribute}`: the label of the attribute being validated
 47      * - `{value}`: the value of the attribute being validated
 48      * - `{requiredValue}`: the value of [[requiredValue]]
 49      */
 50     public $message;
 51 
 52 
 53     /**
 54      * @inheritdoc
 55      */
 56     public function init()
 57     {
 58         parent::init();
 59         if ($this->message === null) {
 60             $this->message = $this->requiredValue === null ? Yii::t('yii', '{attribute} cannot be blank.')
 61                 : Yii::t('yii', '{attribute} must be "{requiredValue}".');
 62         }
 63     }
 64 
 65     /**
 66      * @inheritdoc
 67      */
 68     protected function validateValue($value)
 69     {
 70         if ($this->requiredValue === null) {
 71             if ($this->strict && $value !== null || !$this->strict && !$this->isEmpty(is_string($value) ? trim($value) : $value)) {
 72                 return null;
 73             }
 74         } elseif (!$this->strict && $value == $this->requiredValue || $this->strict && $value === $this->requiredValue) {
 75             return null;
 76         }
 77         if ($this->requiredValue === null) {
 78             return [$this->message, []];
 79         } else {
 80             return [$this->message, [
 81                 'requiredValue' => $this->requiredValue,
 82             ]];
 83         }
 84     }
 85 
 86     /**
 87      * @inheritdoc
 88      */
 89     public function clientValidateAttribute($model, $attribute, $view)
 90     {
 91         ValidationAsset::register($view);
 92         $options = $this->getClientOptions($model, $attribute);
 93 
 94         return 'yii.validation.required(value, messages, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ');';
 95     }
 96 
 97     /**
 98      * @inheritdoc
 99      */
100     public function getClientOptions($model, $attribute)
101     {
102         $options = [];
103         if ($this->requiredValue !== null) {
104             $options['message'] = $this->formatMessage($this->message, [
105                 'requiredValue' => $this->requiredValue,
106             ]);
107             $options['requiredValue'] = $this->requiredValue;
108         } else {
109             $options['message'] = $this->message;
110         }
111         if ($this->strict) {
112             $options['strict'] = 1;
113         }
114 
115         $options['message'] = $this->formatMessage($options['message'], [
116             'attribute' => $model->getAttributeLabel($attribute),
117         ]);
118 
119         return $options;
120     }
121 }

这个验证器用于验证非空非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的值。

 

posted @ 2018-01-19 17:25  菜鸟江太公  阅读(253)  评论(0编辑  收藏  举报