yii2源码学习笔记(六)

Posted dragon16

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了yii2源码学习笔记(六)相关的知识,希望对你有一定的参考价值。

Behvaior类,Behavior类是所有事件类的基类:

目录yii2\base\Behavior.php

 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\base;
 9 
10 /**
11  * Behavior is the base class for all behavior classes.
12  * 所有行为的基类
13  * A behavior can be used to enhance the functionality of an existing component without modifying its code.
14  * In particular, it can "inject" its own methods and properties into the component
15  * and make them directly accessible via the component. It can also respond to the events triggered in the component
16  * and thus intercept the normal code execution.
17  * 用来增强现有组件的功能而不修改它的代码。它可以添加自己的方法和属性组件
18  * 使他们可以直接通过组件访问。还可以响应组件触发的事件,拦截正常的代码执行。
19  * @author Qiang Xue <[email protected]>
20  * @since 2.0
21  * 继承父类Object
22  */
23 class Behavior extends Object
24 {
25     /**
26      * @var Component the owner of this behavior 要附加行为对象的组件。
27      */
28     public $owner;
29 
30 
31     /**
32      * Declares event handlers for the [[owner]]‘s events.
33      * 声明[[owner]]的事件处理程序
34      * Child classes may override this method to declare what PHP callbacks should
35      * be attached to the events of the [[owner]] component.
36      * 子类可以重写此方法 php回调应连接 [[owner]]组件。
37      * The callbacks will be attached to the [[owner]]‘s events when the behavior is
38      * attached to the owner; and they will be detached from the events when
39      * the behavior is detached from the component.
40      * 当行为被连接到owner时回调将附在[[owner]]的事件中,当行为从组件中分离时,它们将被分离
41      * The callbacks can be any of the followings:
42      *
43      * - method in this behavior: `‘handleClick‘`, equivalent to `[$this, ‘handleClick‘]`
44      * - object method: `[$object, ‘handleClick‘]`
45      * - static method: `[‘Page‘, ‘handleClick‘]`
46      * - anonymous function: `function ($event) { ... }`
47      *
48      * The following is an example:
49      *
50      * ~~~
51      * [
52      *     Model::EVENT_BEFORE_VALIDATE => ‘myBeforeValidate‘,
53      *     Model::EVENT_AFTER_VALIDATE => ‘myAfterValidate‘,
54      * ]
55      * ~~~
56      *
57      * @return array events (array keys) and the corresponding event handler methods (array values).
58      * 事件和相应的事件处理方法
59      */
60     public function events()
61     {
62         return [];
63     }
64 
65     /**
66      * Attaches the behavior object to the component.绑定行为到组件
67      * The default implementation will set the [[owner]] property   
68      * and attach event handlers as declared in [[events]].
69      * 默认设置[[owner]]属性并将事件处理程序绑定到组件
70      * Make sure you call the parent implementation if you override this method. 如果重写方法,确保调用父类去实现
71      * @param Component $owner the component that this behavior is to be attached to. 行为绑定到$owner组件
72      */
73     public function attach($owner)
74     {
75        $this->owner = $owner;//设置 $owner ,使得所依附的对象可以访问、操作
76         foreach ($this->events() as $event => $handler) {
77             //将准备响应的事件,通过所依附类的 on()方法 绑定到类上
78             $owner->on($event, is_string($handler) ? [$this, $handler] : $handler);
79         }
80     }
81 
82     /**
83      * Detaches the behavior object from the component. 解除绑定的行为
84      * The default implementation will unset the [[owner]] property 默认取消 owner的属性
85      * and detach event handlers declared in [[events]].    将events中的事件程序解除绑定
86      * Make sure you call the parent implementation if you override this method.如果重写方法,确保调用父类去实现
87      */
88     public function detach()
89     {
90         if ($this->owner) {
91             foreach ($this->events() as $event => $handler) {//遍历行为中 events() 返回的数组
92                 //通过Component的 off() 将绑定到类上的事件解除
93                 $this->owner->off($event, is_string($handler) ? [$this, $handler] : $handler);
94             }
95             $this->owner = null;//将 $owner 设置为 null ,表示这个解除绑定
96         }
97     }
98 }

 接下来看一下model类,它是所有模型的基类

目录yii2\base\Model.php

  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\base;
  9 
 10 use Yii;
 11 use ArrayAccess;
 12 use ArrayObject;
 13 use ArrayIterator;
 14 use ReflectionClass;
 15 use IteratorAggregate;
 16 use yii\helpers\Inflector;
 17 use yii\validators\RequiredValidator;
 18 use yii\validators\Validator;
 19 
 20 /**
 21  * Model is the base class for data models.
 22  *
 23  * IteratorAggregate(聚合式迭代器)接口 — 创建外部迭代器的接口, 需实现 getIterator 方法。
 24  * IteratorAggregate::getIterator — 获取一个外部迭代器, foreach 会调用该方法。
 25  *
 26  * ArrayAccess(数组式访问)接口 — 提供像访问数组一样访问对象的能力的接口, 需实现如下方法:
 27  * ArrayAccess::offsetExists — 检查一个偏移位置是否存在
 28  * ArrayAccess::offsetGet — 获取一个偏移位置的值
 29  * ArrayAccess::offsetSet — 设置一个偏移位置的值
 30  * ArrayAccess::offsetUnset — 复位一个偏移位置的值
 31  * 在 Model 中用于实现将 $model[$field] 替换为 $model->$field
 32  *
 33  * Model implements the following commonly used features:
 34  *
 35  * - attribute declaration: by default, every public class member is considered as
 36  *   a model attribute
 37  * - attribute labels: each attribute may be associated with a label for display purpose
 38  * - massive attribute assignment
 39  * - scenario-based validation
 40  *
 41  * Model also raises the following events when performing data validation:
 42  *
 43  * - [[EVENT_BEFORE_VALIDATE]]: an event raised at the beginning of [[validate()]]
 44  * - [[EVENT_AFTER_VALIDATE]]: an event raised at the end of [[validate()]]
 45  *
 46  * You may directly use Model to store model data, or extend it with customization.
 47  *
 48  * @property \yii\validators\Validator[] $activeValidators The validators applicable to the current
 49  * [[scenario]]. This property is read-only.
 50  * @property array $attributes Attribute values (name => value).
 51  * @property array $errors An array of errors for all attributes. Empty array is returned if no error. The
 52  * result is a two-dimensional array. See [[getErrors()]] for detailed description. This property is read-only.
 53  * @property array $firstErrors The first errors. The array keys are the attribute names, and the array values
 54  * are the corresponding error messages. An empty array will be returned if there is no error. This property is
 55  * read-only.
 56  * @property ArrayIterator $iterator An iterator for traversing the items in the list. This property is
 57  * read-only.
 58  * @property string $scenario The scenario that this model is in. Defaults to [[SCENARIO_DEFAULT]].
 59  * @property ArrayObject|\yii\validators\Validator[] $validators All the validators declared in the model.
 60  * This property is read-only.
 61  *
 62  * @author Qiang Xue <[email protected]>
 63  * @since 2.0
 64  */
 65 class Model extends Component implements IteratorAggregate, ArrayAccess, Arrayable
 66 {
 67     use ArrayableTrait;
 68 
 69     /**
 70      * The name of the default scenario.
 71      * 默认场景的名称
 72      */
 73     const SCENARIO_DEFAULT = default;
 74     /**
 75      * @event ModelEvent an event raised at the beginning of [[validate()]]. You may set
 76      * [[ModelEvent::isValid]] to be false to stop the validation.
 77      */
 78     const EVENT_BEFORE_VALIDATE = beforeValidate;
 79     /**
 80      * @event Event an event raised at the end of [[validate()]]
 81      */
 82     const EVENT_AFTER_VALIDATE = afterValidate;
 83 
 84     /**
 85      * @var array validation errors (attribute name => array of errors)
 86      * 验证的错误信息
 87      */
 88     private $_errors;
 89     /**
 90      * @var ArrayObject list of validators
 91      */
 92     private $_validators;
 93     /**
 94      * @var string current scenario
 95      * 当前的场景,默认是default
 96      */
 97     private $_scenario = self::SCENARIO_DEFAULT;
 98 
 99 
100     /**
101      * Returns the validation rules for attributes.
102      *
103      * 返回属性的验证规则
104      *
105      * Validation rules are used by [[validate()]] to check if attribute values are valid.
106      * Child classes may override this method to declare different validation rules.
107      *
108      * Each rule is an array with the following structure:
109      *
110      * ~~~
111      * [
112      *     [‘attribute1‘, ‘attribute2‘],
113      *     ‘validator type‘,
114      *     ‘on‘ => [‘scenario1‘, ‘scenario2‘],
115      *     ...other parameters...
116      * ]
117      * ~~~
118      *
119      * where
120      *
121      *  - attribute list: required, specifies the attributes array to be validated, for single attribute you can pass string;
122      *  - validator type: required, specifies the validator to be used. It can be a built-in validator name,
123      *    a method name of the model class, an anonymous function, or a validator class name.
124      *  - on: optional, specifies the [[scenario|scenarios]] array when the validation
125      *    rule can be applied. If this option is not set, the rule will apply to all scenarios.
126      *  - additional name-value pairs can be specified to initialize the corresponding validator properties.
127      *    Please refer to individual validator class API for possible properties.
128      *
129      * A validator can be either an object of a class extending [[Validator]], or a model class method
130      * (called *inline validator*) that has the following signature:
131      *
132      * ~~~
133      * // $params refers to validation parameters given in the rule
134      * function validatorName($attribute, $params)
135      * ~~~
136      *
137      * In the above `$attribute` refers to currently validated attribute name while `$params` contains an array of
138      * validator configuration options such as `max` in case of `string` validator. Currently validate attribute value
139      * can be accessed as `$this->[$attribute]`.
140      *
141      * Yii also provides a set of [[Validator::builtInValidators|built-in validators]].
142      * They each has an alias name which can be used when specifying a validation rule.
143      *
144      * Below are some examples:
145      *
146      * ~~~
147      * [
148      *     // built-in "required" validator
149      *     [[‘username‘, ‘password‘], ‘required‘],
150      *     // built-in "string" validator customized with "min" and "max" properties
151      *     [‘username‘, ‘string‘, ‘min‘ => 3, ‘max‘ => 12],
152      *     // built-in "compare" validator that is used in "register" scenario only
153      *     [‘password‘, ‘compare‘, ‘compareAttribute‘ => ‘password2‘, ‘on‘ => ‘register‘],
154      *     // an inline validator defined via the "authenticate()" method in the model class
155      *     [‘password‘, ‘authenticate‘, ‘on‘ => ‘login‘],
156      *     // a validator of class "DateRangeValidator"
157      *     [‘dateRange‘, ‘DateRangeValidator‘],
158      * ];
159      * ~~~
160      *
161      * Note, in order to inherit rules defined in the parent class, a child class needs to
162      * merge the parent rules with child rules using functions such as `array_merge()`.
163      *
164      * @return array validation rules
165      * @see scenarios()
166      */
167     public function rules()
168     {
169         return [];
170     }
171 
172     /**
173      * Returns a list of scenarios and the corresponding active attributes.
174      * An active attribute is one that is subject to validation in the current scenario.
175      * 返回场景及与之对应的 active 属性的列表
176      * The returned array should be in the following format:
177      *
178      * ~~~
179      * [
180      *     ‘scenario1‘ => [‘attribute11‘, ‘attribute12‘, ...],
181      *     ‘scenario2‘ => [‘attribute21‘, ‘attribute22‘, ...],
182      *     ...
183      * ]
184      * ~~~
185      *
186      * By default, an active attribute is considered safe and can be massively assigned.
187      * If an attribute should NOT be massively assigned (thus considered unsafe),
188      * please prefix the attribute with an exclamation character (e.g. ‘!rank‘).
189      *
190      * The default implementation of this method will return all scenarios found in the [[rules()]]
191      * declaration. A special scenario named [[SCENARIO_DEFAULT]] will contain all attributes
192      * found in the [[rules()]]. Each scenario will be associated with the attributes that
193      * are being validated by the validation rules that apply to the scenario.
194      *
195      * @return array a list of scenarios and the corresponding active attributes.
196      */
197     public function scenarios()
198     {
199         // 默认有 default 的场景
200         $scenarios = [self::SCENARIO_DEFAULT => []];
201         foreach ($this->getValidators() as $validator) {
202             // 循环 validator,取出所有提到的场景,包括 on 和 except
203             foreach ($validator->on as $scenario) {
204                 $scenarios[$scenario] = [];
205             }
206             foreach ($validator->except as $scenario) {
207                 $scenarios[$scenario] = [];
208             }
209         }
210         // 取出所有场景的名称
211         $names = array_keys($scenarios);
212 
213         foreach ($this->getValidators() as $validator) {
214             if (empty($validator->on) && empty($validator->except)) {
215                 // 如果 validator 即没有定义 on,也没有定义 except,就放到所有的场景中
216                 foreach ($names as $name) {
217                     // 循环 $validator 的所有属性
218                     foreach ($validator->attributes as $attribute) {
219                         $scenarios[$name][$attribute] = true;
220                     }
221                 }
222             } elseif (empty($validator->on)) {
223                 // 如果没有定义 on
224                 foreach ($names as $name) {
225                     if (!in_array($name, $validator->except, true)) {
226                         // 而且场景不在 except 中, 就将这个属性加入到相应的场景中
227                         foreach ($validator->attributes as $attribute) {
228                             $scenarios[$name][$attribute] = true;
229                         }
230                     }
231                 }
232             } else {
233                 // 如果定义了 on
234                 foreach ($validator->on as $name) {
235                     // 就将这个属性加入到 on 定义的场景中
236                     foreach ($validator->attributes as $attribute) {
237                         $scenarios[$name][$attribute] = true;
238                     }
239                 }
240             }
241         }
242 
243         /**
244          * 将 $scenarios 从
245          *
246          * ~~~
247          * [
248          *     ‘default‘ => [],
249          *     ‘scenario1‘ => [‘attribute11‘ => true, ‘attribute12‘ => true, ...],
250          *     ‘scenario2‘ => [‘attribute21‘ => true, ‘attribute22‘ => true, ...],
251          *     ‘scenario3‘ => [],
252          *     ...
253          * ]
254          * ~~~
255          * 转化为
256          * ~~~
257          * [
258          *     ‘default‘ => [],
259          *     ‘scenario1‘ => [‘attribute11‘, ‘attribute12‘, ...],
260          *     ‘scenario2‘ => [‘attribute21‘, ‘attribute22‘, ...],
261          *     ...
262          * ]
263          * ~~~
264          */
265         foreach ($scenarios as $scenario => $attributes) {
266             // 去除掉没有属性值的场景
267             if (empty($attributes) && $scenario !== self::SCENARIO_DEFAULT) {
268                 unset($scenarios[$scenario]);
269             } else {
270                 // 取出场景中的属性名称
271                 $scenarios[$scenario] = array_keys($attributes);
272             }
273         }
274 
275         return $scenarios;
276     }

未完待续

以上是关于yii2源码学习笔记(六)的主要内容,如果未能解决你的问题,请参考以下文章

yii2源码学习笔记(三)

yii2源码学习笔记(十九)

yii2源码学习笔记(十六)

yii2源码学习笔记(四)

yii2源码学习笔记(七)

yii2源码学习笔记(五)