今天我们来看一下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