zoukankan      html  css  js  c++  java
  • yii2框架随笔10

    今天我们来看一下Model.php

    目录:base/Model.php

    <?php
    /**
     * @link http://www.yiiframework.com/
     * @copyright Copyright (c) 2008 Yii Software LLC
     * @license http://www.yiiframework.com/license/
     */
    namespace yiibase;
    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
     * 基于场景的验证
    
     */
     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.
         * 事件ModelEvent 一个事件浮出是由[validate()]事件开始的,你可以设置[ModelEvent::isValid]让它变为假以停止验证。
         */
        const EVENT_BEFORE_VALIDATE = 'beforeValidate';
        /**
         * @event Event an event raised at the end of [[validate()]]
         * 一个事件结束于[[validate()]]方法。
         */
        const EVENT_AFTER_VALIDATE = 'afterValidate';
        /**
         * @var array validation errors (attribute name => array of errors)
         * 验证的错误信息
         */
        private $_errors;
        /**
         * @var ArrayObject list of validators
         * ArrayObject验证器列表
         */
        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.
         * 验证规则是使用[[validate()]]检查属性值是否有效。
         * 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...
         * ]
         * ~~~
         */
           public function rules()
        {
            return [];
        }
    
    
    /**
         * Returns a list of scenarios and the corresponding active attributes.
         * 返回场景及与之对应的 active 属性的列表
         * The returned array should be in the following format:
         * 返回的数组应该遵循以下格式
         * ~~~
         * [
         *     'scenario1' => ['attribute11', 'attribute12', ...],
         *     'scenario2' => ['attribute21', 'attribute22', ...],
         *     ...
         * ]
         * ~~~
         *
         *
         * @return array a list of scenarios and the corresponding active attributes.
         * 返回一个场景和属性列表。
         */
        public function scenarios()
        {
            
            $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) {
                      
                        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)) {
                            
                            foreach ($validator->attributes as $attribute) {
                                $scenarios[$name][$attribute] = true;
                            }
                        }
                    }
                } else {
                    // 如果定义了 on
                    foreach ($validator->on as $name) {
                        
                        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 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;
        }
  • 相关阅读:
    Java异常处理和设计
    一次qps测试实践
    Alternate Task UVA
    Just Another Problem UVA
    Lattice Point or Not UVA
    Play with Floor and Ceil UVA
    Exploring Pyramids UVALive
    Cheerleaders UVA
    Triangle Counting UVA
    Square Numbers UVA
  • 原文地址:https://www.cnblogs.com/taokai/p/5414881.html
Copyright © 2011-2022 走看看