Model类,集中整个应用的数据和业务逻辑——场景、属性和标签:

  /**
      * 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 属性的列表
      * active 属性是指在默认场景中验证的
      * The returned array should be in the following format:
      * 返回的格式如下:
      * ```php
      * [
      *     'scenario1' => ['attribute11', 'attribute12', ...],
      *     'scenario2' => ['attribute21', 'attribute22', ...],
      *     ...
      * ]
      * ```
      *
      * By default, an active attribute is considered safe and can be massively assigned.
      * 默认情况下,一个active属性被认为是安全的,可以被批量赋值
      * 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.
      * 默认情况下会返回[[rules()]]中定义的所有场景,其中[[SCENARIO_DEFAULT]] 默认场景包含所有的属性
      * 每个场景对应的属性值将按指定的验证规则验证
      *
      * @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)) {
                 // 取出场景中的属性名称
                 $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 [[\yii\widgets\ActiveForm]] 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".
      * 表单名称用于[[\yii\widgets\ActiveForm]]确定模型中的属性名对应的输入域的名称
      * 如果表单名为A,属性名为b,对应的输入名为A[b],如果表单名为空,则输入名为b
      *
      * The purpose of the above naming schema is that for forms which contain multiple different models,
      * the attributes of each model are grouped in sub-arrays of the POST-data and it is easier to
      * differentiate between them.
      * 上述命名模式的目的是,对于包含多个不同模型的表单,每个模型的属性分组在对应的表单名下的数组,能更好的区分它们
      *
      * 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.
      * @see load()
      */
     public function formName()
     {
         // ReflectionClass 类,是php内置的反射类,用于获取类的信息,包含了一个类的有关信息
         $reflector = new ReflectionClass($this);
         // 获取类的短名,就是不含命名空间(namespace)的那一部分
         return $reflector->getShortName();
     }

     /**
      * Returns the list of attribute names.
      * 返回属性名的列表
      *
      * By default, this method returns all public non-static properties of the class.
      * You may override this method to change the default behavior.
      * 默认只会返回 public 且不是 static 的属性,可以重写该方法定义不同的返回类型
      *
      * @return array list of attribute names.
      */
     public function attributes()
     {
         $class = new ReflectionClass($this);
         $names = [];
         /**
          *ReflectionClass::getProperties — ReflectionClass反射类的方法,用于获取一组属性,有下列参数:
           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;
     }

     /**
      * Returns the attribute labels.
      * 返回属性的标签
      *
      * Attribute labels are mainly used for display purpose. For example, given an attribute
      * `firstName`, we can declare a label `First Name` which is more user-friendly and can
      * be displayed to end users.
      * 属性标签主要用于显示目的,例如给属性'firstName'一个‘First Name’标签,能够更友好的显示给最终用户
      *
      * By default an attribute label is generated using [[generateAttributeLabel()]].
      * This method allows you to explicitly specify attribute labels.
      * 默认调用[[generateAttributeLabel()]]方法生成标签
      * Note, in order to inherit labels defined in the parent class, a child class needs to
      * merge the parent labels with child labels using functions such as `array_merge()`.
      * 注意,为了继承父类的标签,之类需要调用`array_merge()`合并父类的标签
      *
      * @return array attribute labels (name => label)
      * @see generateAttributeLabel()
      */
     public function attributeLabels()
     {
         return [];
     }

Yii源码阅读笔记(十四)的更多相关文章

  1. Yii源码阅读笔记(四)

    所有控制器action的基类yii\base\Action.php namespace yii\base;//定义的命名空间 use Yii //使用的命名空间 class Action extend ...

  2. Mina源码阅读笔记(四)—Mina的连接IoConnector2

    接着Mina源码阅读笔记(四)-Mina的连接IoConnector1,,我们继续: AbstractIoAcceptor: 001 package org.apache.mina.core.rewr ...

  3. Yii源码阅读笔记(一)

    今天开始阅读yii2的源码,想深入了解一下yii框架的工作原理,同时学习一下优秀的编码规范和风格.在此记录一下阅读中的小心得. 每个框架都有一个入口文件,首先从入口文件开始,yii2的入口文件位于we ...

  4. Vue2.0源码阅读笔记(四):nextTick

      在阅读 nextTick 的源码之前,要先弄明白 JS 执行环境运行机制,介绍 JS 执行环境的事件循环机制的文章很多,大部分都阐述的比较笼统,甚至有些文章说的是错误的,以下为个人理解,如有错误, ...

  5. Mina源码阅读笔记(四)—Mina的连接IoConnector1

    上一篇写的是IoAcceptor是服务器端的接收代码,今天要写的是IoConnector,是客户端的连接器.在昨天,我们还留下一些问题没有解决,这些问题今天同样会产生,但是都要等到讲到session的 ...

  6. Yii源码阅读笔记(三十四)

    Instance类, 表示依赖注入容器或服务定位器中对某一个对象的引用 namespace yii\di; use Yii; use yii\base\InvalidConfigException; ...

  7. Yii源码阅读笔记(二十四)

    Module类中获取子模块,注册子模块,实例化控制器,根据路由运行指定控制器方法的注释: /** * Retrieves the child module of the specified ID. * ...

  8. Yii源码阅读笔记(三十五)

    Container,用于动态地创建.注入依赖单元,映射依赖关系等功能,减少了许多代码量,降低代码耦合程度,提高项目的可维护性. namespace yii\di; use ReflectionClas ...

  9. Yii源码阅读笔记(三十二)

    web/Application类的注释,继承base/Application类,针对web应用的一些处理: namespace yii\web; use Yii; use yii\base\Inval ...

随机推荐

  1. nginx 匹配.zip .apk 结尾的文件 直接下载

    server { listen 80; server_name ok.xidd.com; index index.html index.htm index.php; root /alidata/www ...

  2. Git自动部署

    Git自动部署文件位于repository下面的hooks里的post-receive #!/bin/sh set -e git-update-server-info gitosis-run-hook ...

  3. .net学习之类与对象、new关键字、构造函数、常量和只读变量、枚举、结构、垃圾回收、静态成员、静态类等

    1.类与对象的关系类是对一类事务的统称,是抽象的,不能拿来直接使用,比如汽车,没有具体指哪一辆汽车对象是一个具体存在的,看的见,摸得着的,可以拿来直接使用,比如我家的那辆刚刚买的新汽车,就是具体的对象 ...

  4. Java Hour 49 保存和查询历史的Weather

    吾一直坚信,是需求的不断变化推动了架构的不断演变. 新的需求 能够查看指定日期的Weather,因为客户想要比较昨天和今天的天气情况,所以需要能够查询历史数据的功能. 1 能保存当前的天气到数据库 2 ...

  5. javascript 复习代码

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  6. Action类为何要 extends ActionSupport

    我做的时候,我的action是继承ActionSupport的 Struts 2的Action无须实现任何接口或继承任何类型,普通的POJO类就可以用做Action类,但是,我们为了方便实现Actio ...

  7. 51 NOD 1685 第K大区间2 二分+BIT

    题目描述: 定义一个长度为奇数的区间的值为其所包含的的元素的中位数. 现给出n个数,求将所有长度为奇数的区间的值排序后,第K大的值为多少. 样例解释: [l,r]表示区间的值 [1]:3 [2]:1 ...

  8. Android横屏竖屏切换的问题

    Android横屏竖屏切换的问题 http://blog.sina.com.cn/s/blog_77c632410101790w.html

  9. javascript优化--03高质量编码

    使用Object的直接量实例构造轻量级的字典: 使用for/in循环,使用对象字面量来构建,并确保不增加Object.prototype属性来导致for/in循环:(考虑到兼容性,如Array.pro ...

  10. Booklet Printing[HDU1117]

    Booklet Printing Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...