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 yii\base;
use Yii;
use ArrayAccess;
use ArrayObject;
use ArrayIterator;
use ReflectionClass;
use IteratorAggregate;
use yii\helpers\Inflector;
use yii\validators\RequiredValidator;
use yii\validators\Validator;
/**
 * 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‘, ...],
     *     ...
     * ]
     * ~~~
     *
     * 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‘).
     * 请在感叹字符前加一个前缀属性例如(e.g. ‘!rank‘).
     * The default implementation of this method will return all scenarios found in the [[rules()]]
     * declaration.
     * 默认该方法的实现将会返回所有场景中发现的[rules()]方法的声明。
     *  A special scenario named [[SCENARIO_DEFAULT]] will contain all attributes
     * found in the [[rules()]].
     * 一个特殊的场景叫[[SCENARIO_DEFAULT]]将包含所有属性
     * 在[[rules()]]里。
     *
     * @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 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;
    }
时间: 2024-10-16 11:54:52

yii2框架随笔10的相关文章

yii2框架随笔21

今天来看一下BaseYii.php <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace yii; use yii\base\InvalidConfigException; use yii\base\InvalidParamExceptio

yii2框架随笔4

接下来我们继续了解Component.php 目录为:vendor/yiisoft/yii2/base/Component.php (接上次的代码) /** * Sets the value of a component property. *设置一个组件属性的值. * This method will check in the following order and act accordingly: *这种方法将检查以下顺序并采取相应的行动: * - a property defined by

yii2框架随笔30

今天来看console/Application.php <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace yii\console; use Yii; use yii\base\InvalidRouteException; /** * A

yii2框架随笔23

今天继续阅读BaseYii.php <?php /** * Class autoload loader. * 自动装载类加载程序. * This method is invoked automatically when PHP sees an unknown class. * PHP用该方法自动调用一个未知类. * The method will attempt to include the class file according to the following procedure: * 方

yii2框架随笔22

今天继续来看BaseYii.php <?php /** * Returns the root alias part of a given alias. * 返回根别名的一部分,一个给定的别名. * A root alias is an alias that has been registered via [[setAlias()]] previously. * 根别名是已经注册别名通过[[setAlias()]]. * If a given alias matches multiple root

yii2框架随笔3

今天开始阅读vendor/yiisoft/yii2/base/Action.php <?php namespace yii\base;//命名空间 use Yii;//加载Yii文件夹下的Yii.php /** * Action is the base class for all controller action classes. * * Action provides a way to reuse action method code. An action method in an Acti

yii2框架随笔36

今天来看一下vendor/yiisoft/yii2/base/Event.php <?php namespace yii\base; //事件是所有事件类的基类.它封装了参数与事件相关联. //如果一个事件处理程序集[[进行]]是真的,其余的,uninvoked处理程序将不再被称为处理事件. //另外,添加一个事件处理程序时,额外的数据可能被传递和可以通过[[数据]]属性调用事件处理程序时. class Event extends Object { /** * @var string the e

yii2框架随笔37

vendor/yiisoft/yii2/base/Event.php <?php namespace yii\base; //事件是所有事件类的基类.它封装了参数与事件相关联. //如果一个事件处理程序集[[进行]]是真的,其余的,uninvoked处理程序将不再被称为处理事件. //另外,添加一个事件处理程序时,额外的数据可能被传递和可以通过[[数据]]属性调用事件处理程序时. class Event extends Object { /** * @var string the event n

yii2框架随笔35

今天来看vendor/yiisoft/yii2/base/Event.php <?php namespace yii\base; //事件是所有事件类的基类.它封装了参数与事件相关联. //如果一个事件处理程序集[[进行]]是真的,其余的,uninvoked处理程序将不再被称为处理事件. //另外,添加一个事件处理程序时,额外的数据可能被传递和可以通过[[数据]]属性调用事件处理程序时. class Event extends Object { /** * @var string the eve