zoukankan      html  css  js  c++  java
  • 学习yii2.0框架阅读代码(七)

    vendor/yiisoft/yii2/base/Model.php

    <?php
    /**
     * @link http://www.yiiframework.com/
     * @copyright Copyright (c) 2008 Yii Software LLC
     * @license http://www.yiiframework.com/license/
     */
    
    namespace yiiase;
    
    use Yii;
    use ArrayAccess;
    use ArrayObject;
    use ArrayIterator;
    use ReflectionClass;
    use IteratorAggregate;
    use yiihelpersInflector;
    use yiivalidatorsRequiredValidator;
    use yiivalidatorsValidator;
    
    /**
     * Model is the base class for data models.
     *
     * IteratorAggregate(聚合式迭代器)接口 — 创建外部迭代器的接口, 需实现 getIterator 方法。
     * IteratorAggregate::getIterator — 获取一个外部迭代器, foreach 会调用该方法。
     *
     * ArrayAccess(数组式访问)接口 — 提供像访问数组一样访问对象的能力的接口, 需实现如下方法:
     * ArrayAccess::offsetExists — 检查一个偏移位置是否存在
     * ArrayAccess::offsetGet — 获取一个偏移位置的值
     * ArrayAccess::offsetSet — 设置一个偏移位置的值
     * ArrayAccess::offsetUnset — 复位一个偏移位置的值
     * 在 Model 中用于实现将 $model[$field] 替换为 $model->$field
     *
     * Model implements the following commonly used features:
     *
     * - attribute declaration: by default, every public class member is considered as
     *   a model attribute
     * - attribute labels: each attribute may be associated with a label for display purpose
     * - massive attribute assignment
     * - scenario-based validation
     *
     * Model also raises the following events when performing data validation:
     *
     * - [[EVENT_BEFORE_VALIDATE]]: an event raised at the beginning of [[validate()]]
     * - [[EVENT_AFTER_VALIDATE]]: an event raised at the end of [[validate()]]
     *
     * You may directly use Model to store model data, or extend it with customization.
     *
     * @property yiivalidatorsValidator[] $activeValidators The validators applicable to the current
     * [[scenario]]. This property is read-only.
     * @property array $attributes Attribute values (name => value).
     * @property array $errors An array of errors for all attributes. Empty array is returned if no error. The
     * result is a two-dimensional array. See [[getErrors()]] for detailed description. This property is read-only.
     * @property array $firstErrors The first errors. The array keys are the attribute names, and the array values
     * are the corresponding error messages. An empty array will be returned if there is no error. This property is
     * read-only.
     * @property ArrayIterator $iterator An iterator for traversing the items in the list. This property is
     * read-only.
     * @property string $scenario The scenario that this model is in. Defaults to [[SCENARIO_DEFAULT]].
     * @property ArrayObject|yiivalidatorsValidator[] $validators All the validators declared in the model.
     * This property is read-only.
     *
     * @author Qiang Xue <qiang.xue@gmail.com>
     * @since 2.0
     */
    class Model extends Component implements IteratorAggregate, ArrayAccess, Arrayable
    {
        use ArrayableTrait;
    
        /**
         * The name of the default scenario.
         * 默认场景的名称
         */
        const SCENARIO_DEFAULT = 'default';
        /**
         * @event ModelEvent an event raised at the beginning of [[validate()]]. You may set
         * [[ModelEvent::isValid]] to be false to stop the validation.
         */
        const EVENT_BEFORE_VALIDATE = 'beforeValidate';
        /**
         * @event Event an event raised at the end of [[validate()]]
         */
        const EVENT_AFTER_VALIDATE = 'afterValidate';
    
        /**
         * @var array validation errors (attribute name => array of errors)
         * 验证的错误信息
         */
        private $_errors;
        /**
         * @var ArrayObject list of validators
         */
        private $_validators;
        /**
         * @var string current scenario
         * 当前的场景,默认是default
         */
        private $_scenario = self::SCENARIO_DEFAULT;
    
    
        /**
         * Returns the validation rules for attributes.
         *
         * 返回属性的验证规则
         *
         * Validation rules are used by [[validate()]] to check if attribute values are valid.
         * Child classes may override this method to declare different validation rules.
         *
         * Each rule is an array with the following structure:
         *
         * ~~~
         * [
         *     ['attribute1', 'attribute2'],
         *     'validator type',
         *     'on' => ['scenario1', 'scenario2'],
         *     ...other parameters...
         * ]
         * ~~~
         *
         * where
         *
         *  - attribute list: required, specifies the attributes array to be validated, for single attribute you can pass string;
         *  - validator type: required, specifies the validator to be used. It can be a built-in validator name,
         *    a method name of the model class, an anonymous function, or a validator class name.
         *  - on: optional, specifies the [[scenario|scenarios]] array when the validation
         *    rule can be applied. If this option is not set, the rule will apply to all scenarios.
         *  - additional name-value pairs can be specified to initialize the corresponding validator properties.
         *    Please refer to individual validator class API for possible properties.
         *
         * A validator can be either an object of a class extending [[Validator]], or a model class method
         * (called *inline validator*) that has the following signature:
         *
         * ~~~
         * // $params refers to validation parameters given in the rule
         * function validatorName($attribute, $params)
         * ~~~
         *
         * In the above `$attribute` refers to currently validated attribute name while `$params` contains an array of
         * validator configuration options such as `max` in case of `string` validator. Currently validate attribute value
         * can be accessed as `$this->[$attribute]`.
         *
         * Yii also provides a set of [[Validator::builtInValidators|built-in validators]].
         * They each has an alias name which can be used when specifying a validation rule.
         *
         * Below are some examples:
         *
         * ~~~
         * [
         *     // built-in "required" validator
         *     [['username', 'password'], 'required'],
         *     // built-in "string" validator customized with "min" and "max" properties
         *     ['username', 'string', 'min' => 3, 'max' => 12],
         *     // built-in "compare" validator that is used in "register" scenario only
         *     ['password', 'compare', 'compareAttribute' => 'password2', 'on' => 'register'],
         *     // an inline validator defined via the "authenticate()" method in the model class
         *     ['password', 'authenticate', 'on' => 'login'],
         *     // a validator of class "DateRangeValidator"
         *     ['dateRange', 'DateRangeValidator'],
         * ];
         * ~~~
         *
         * Note, in order to inherit rules defined in the parent class, a child class needs to
         * merge the parent rules with child rules using functions such as `array_merge()`.
         *
         * @return array validation rules
         * @see scenarios()
         */
        public function rules()
        {
            return [];
        }
    
        /**
         * Returns a list of scenarios and the corresponding active attributes.
         * An active attribute is one that is subject to validation in the current scenario.
         * 返回场景及与之对应的 active 属性的列表
         * The returned array should be in the following format:
         *
         * ~~~
         * [
         *     'scenario1' => ['attribute11', 'attribute12', ...],
         *     'scenario2' => ['attribute21', 'attribute22', ...],
         *     ...
         * ]
         * ~~~
         *
         * By default, an active attribute is considered safe and can be massively assigned.
         * If an attribute should NOT be massively assigned (thus considered unsafe),
         * please prefix the attribute with an exclamation character (e.g. '!rank').
         *
         * The default implementation of this method will return all scenarios found in the [[rules()]]
         * declaration. A special scenario named [[SCENARIO_DEFAULT]] will contain all attributes
         * found in the [[rules()]]. Each scenario will be associated with the attributes that
         * are being validated by the validation rules that apply to the scenario.
         *
         * @return array a list of scenarios and the corresponding active attributes.
         */
        public function scenarios()
        {
            // 默认有 default 的场景
            $scenarios = [self::SCENARIO_DEFAULT => []];
            foreach ($this->getValidators() as $validator) {
                // 循环 validator,取出所有提到的场景,包括 on 和 except
                foreach ($validator->on as $scenario) {
                    $scenarios[$scenario] = [];
                }
                foreach ($validator->except as $scenario) {
                    $scenarios[$scenario] = [];
                }
            }
            // 取出所有场景的名称
            $names = array_keys($scenarios);
    
            foreach ($this->getValidators() as $validator) {
                if (empty($validator->on) && empty($validator->except)) {
                    // 如果 validator 即没有定义 on,也没有定义 except,就放到所有的场景中
                    foreach ($names as $name) {
                        // 循环 $validator 的所有属性
                        foreach ($validator->attributes as $attribute) {
                            $scenarios[$name][$attribute] = true;
                        }
                    }
                } elseif (empty($validator->on)) {
                    // 如果没有定义 on
                    foreach ($names as $name) {
                        if (!in_array($name, $validator->except, true)) {
                            // 而且场景不在 except 中, 就将这个属性加入到相应的场景中
                            foreach ($validator->attributes as $attribute) {
                                $scenarios[$name][$attribute] = true;
                            }
                        }
                    }
                } else {
                    // 如果定义了 on
                    foreach ($validator->on as $name) {
                        // 就将这个属性加入到 on 定义的场景中
                        foreach ($validator->attributes as $attribute) {
                            $scenarios[$name][$attribute] = true;
                        }
                    }
                }
            }
    
            /**
             * 将 $scenarios 从
             *
             * ~~~
             * [
             *     'default' => [],
             *     'scenario1' => ['attribute11' => true, 'attribute12' => true, ...],
             *     'scenario2' => ['attribute21' => true, 'attribute22' => true, ...],
             *     'scenario3' => [],
             *     ...
             * ]
             * ~~~
             * 转化为
             * ~~~
             * [
             *     'default' => [],
             *     'scenario1' => ['attribute11', 'attribute12', ...],
             *     'scenario2' => ['attribute21', 'attribute22', ...],
             *     ...
             * ]
             * ~~~
             */
            foreach ($scenarios as $scenario => $attributes) {
                // 去除掉没有属性值的场景
                if (empty($attributes) && $scenario !== self::SCENARIO_DEFAULT) {
                    unset($scenarios[$scenario]);
                } else {
                    // 取出场景中的属性名称
                    $scenarios[$scenario] = array_keys($attributes);
                }
            }
    
            return $scenarios;
        }
    
        /**
         * Returns the form name that this model class should use.
         *
         * 返回表单的名称,就是这个 model 的类名
         *
         * The form name is mainly used by [[yiiwidgetsActiveForm]] to determine how to name
         * the input fields for the attributes in a model. If the form name is "A" and an attribute
         * name is "b", then the corresponding input name would be "A[b]". If the form name is
         * an empty string, then the input name would be "b".
         *
         * By default, this method returns the model class name (without the namespace part)
         * as the form name. You may override it when the model is used in different forms.
         *
         * @return string the form name of this model class.
         */
        public function formName()
        {
            // ReflectionClass 类包含了一个类的有关信息
            $reflector = new ReflectionClass($this);
            // 获取类的短名,就是不含命名空间(namespace)的那一部分
            return $reflector->getShortName();
        }
    
        /**
         * Returns the list of attribute names.
         * 返回属性名的列表,注意:只会返回 public 且不是 static 的属性
         * By default, this method returns all public non-static properties of the class.
         * You may override this method to change the default behavior.
         * @return array list of attribute names.
         */
        public function attributes()
        {
            $class = new ReflectionClass($this);
            $names = [];
            // ReflectionClass::getProperties — 获取一组属性
            // ReflectionProperty::IS_STATIC 指示了 static 的属性。
            // ReflectionProperty::IS_PUBLIC 指示了 public 的属性。
            // ReflectionProperty::IS_PROTECTED 指示了 protected 的属性。
            // ReflectionProperty::IS_PRIVATE 指示了 private 的属性。
            foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
                // 如果是public的属性,并且不是static的,就认为是它的attribute
                if (!$property->isStatic()) {
                    // 获取该属性的名称
                    $names[] = $property->getName();
                }
            }
    
            return $names;
        }
  • 相关阅读:
    阿里terway源码分析
    golang timeoutHandler解析及kubernetes中的变种
    第四章 控制和循环
    关于 自媒体的声明
    java用正则表达式获取url的域名
    javaweb三大核心基础技术
    NumPy之计算两个矩阵的成对平方欧氏距离
    C/C++之计算两个整型的平均值
    C/C++代码优化之整型除以2的指数并四舍五入
    SSE系列内置函数中的shuffle函数
  • 原文地址:https://www.cnblogs.com/xwzj/p/5402953.html
Copyright © 2011-2022 走看看