zoukankan      html  css  js  c++  java
  • yii2源码学习笔记(七)

    今天继续了解model类

    1   /**
      2      * Returns the form name that this model class should use.
      3      *
      4      * 返回表单的名称,就是这个 model 的类名
      5      *
      6      * The form name is mainly used by [[yiiwidgetsActiveForm]] to determine how to name
      7      * the input fields for the attributes in a model. If the form name is "A" and an attribute
      8      * name is "b", then the corresponding input name would be "A[b]". If the form name is
      9      * an empty string, then the input name would be "b".
     10      *
     11      * By default, this method returns the model class name (without the namespace part)
     12      * as the form name. You may override it when the model is used in different forms.
     13      *
     14      * @return string the form name of this model class.
     15      */
     16     public function formName()
     17     {
     18         // ReflectionClass 类包含了一个类的有关信息
     19         $reflector = new ReflectionClass($this);
     20         // 获取类的短名,就是不含命名空间(namespace)的那一部分
     21         return $reflector->getShortName();
     22     }
     23 
     24     /**
     25      * Returns the list of attribute names.
     26      * 返回属性名的列表,注意:只会返回 public 且不是 static 的属性
     27      * By default, this method returns all public non-static properties of the class.
     28      * You may override this method to change the default behavior.
     29      * @return array list of attribute names.
     30      */
     31     public function attributes()
     32     {
     33         $class = new ReflectionClass($this);
     34         $names = [];
     35         // ReflectionClass::getProperties — 获取一组属性
     36         // ReflectionProperty::IS_STATIC 指示了 static 的属性。
     37         // ReflectionProperty::IS_PUBLIC 指示了 public 的属性。
     38         // ReflectionProperty::IS_PROTECTED 指示了 protected 的属性。
     39         // ReflectionProperty::IS_PRIVATE 指示了 private 的属性。
     40         foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
     41             // 如果是public的属性,并且不是static的,就认为是它的attribute
     42             if (!$property->isStatic()) {
     43                 // 获取该属性的名称
     44                 $names[] = $property->getName();
     45             }
     46         }
     47 
     48         return $names;
     49     }
     50 
     51     /**
     52      * Returns the attribute labels.
     53      * 返回属性的标签
     54      *
     55      * Attribute labels are mainly used for display purpose. For example, given an attribute
     56      * `firstName`, we can declare a label `First Name` which is more user-friendly and can
     57      * be displayed to end users.
     58      *
     59      * By default an attribute label is generated using [[generateAttributeLabel()]].
     60      * This method allows you to explicitly specify attribute labels.
     61      *
     62      * Note, in order to inherit labels defined in the parent class, a child class needs to
     63      * merge the parent labels with child labels using functions such as `array_merge()`.
     64      *
     65      * @return array attribute labels (name => label)
     66      * @see generateAttributeLabel()
     67      */
     68     public function attributeLabels()
     69     {
     70         return [];
     71     }
     72 
     73     /**
     74      * Performs the data validation.
     75      *
     76      * This method executes the validation rules applicable to the current [[scenario]].
     77      * The following criteria are used to determine whether a rule is currently applicable:
     78      *
     79      * - the rule must be associated with the attributes relevant to the current scenario;
     80      * - the rules must be effective for the current scenario.
     81      *
     82      * This method will call [[beforeValidate()]] and [[afterValidate()]] before and
     83      * after the actual validation, respectively. If [[beforeValidate()]] returns false,
     84      * the validation will be cancelled and [[afterValidate()]] will not be called.
     85      *
     86      * Errors found during the validation can be retrieved via [[getErrors()]],
     87      * [[getFirstErrors()]] and [[getFirstError()]].
     88      *
     89      * @param array $attributeNames list of attribute names that should be validated.
     90      * If this parameter is empty, it means any attribute listed in the applicable
     91      * validation rules should be validated.
     92      * @param boolean $clearErrors whether to call [[clearErrors()]] before performing validation
     93      * @return boolean whether the validation is successful without any error.
     94      * @throws InvalidParamException if the current scenario is unknown.
     95      */
     96     public function validate($attributeNames = null, $clearErrors = true)
     97     {
     98         if ($clearErrors) {
     99             $this->clearErrors();
    100         }
    101 
    102         if (!$this->beforeValidate()) {
    103             return false;
    104         }
    105 
    106         $scenarios = $this->scenarios();
    107         $scenario = $this->getScenario();
    108         if (!isset($scenarios[$scenario])) {
    109             throw new InvalidParamException("Unknown scenario: $scenario");
    110         }
    111 
    112         if ($attributeNames === null) {
    113             $attributeNames = $this->activeAttributes();
    114         }
    115 
    116         foreach ($this->getActiveValidators() as $validator) {
    117             $validator->validateAttributes($this, $attributeNames);
    118         }
    119         $this->afterValidate();
    120 
    121         return !$this->hasErrors();
    122     }
    123 
    124     /**
    125      * This method is invoked before validation starts.
    126      * The default implementation raises a `beforeValidate` event.
    127      * You may override this method to do preliminary checks before validation.
    128      * Make sure the parent implementation is invoked so that the event can be raised.
    129      * @return boolean whether the validation should be executed. Defaults to true.
    130      * If false is returned, the validation will stop and the model is considered invalid.
    131      */
    132     public function beforeValidate()
    133     {
    134         $event = new ModelEvent;
    135         $this->trigger(self::EVENT_BEFORE_VALIDATE, $event);
    136 
    137         return $event->isValid;
    138     }
    139 
    140     /**
    141      * This method is invoked after validation ends.
    142      * The default implementation raises an `afterValidate` event.
    143      * You may override this method to do postprocessing after validation.
    144      * Make sure the parent implementation is invoked so that the event can be raised.
    145      */
    146     public function afterValidate()
    147     {
    148         $this->trigger(self::EVENT_AFTER_VALIDATE);
    149     }
    150 
    151     /**
    152      * Returns all the validators declared in [[rules()]].
    153      *
    154      * This method differs from [[getActiveValidators()]] in that the latter
    155      * only returns the validators applicable to the current [[scenario]].
    156      *
    157      * Because this method returns an ArrayObject object, you may
    158      * manipulate it by inserting or removing validators (useful in model behaviors).
    159      * For example,
    160      *
    161      * ~~~
    162      * $model->validators[] = $newValidator;
    163      * ~~~
    164      *
    165      * @return ArrayObject|yiivalidatorsValidator[] all the validators declared in the model.
    166      */
    167     public function getValidators()
    168     {
    169         if ($this->_validators === null) {
    170             $this->_validators = $this->createValidators();
    171         }
    172         return $this->_validators;
    173     }
    174 
    175     /**
    176      * Returns the validators applicable to the current [[scenario]].
    177      * @param string $attribute the name of the attribute whose applicable validators should be returned.
    178      * If this is null, the validators for ALL attributes in the model will be returned.
    179      * @return yiivalidatorsValidator[] the validators applicable to the current [[scenario]].
    180      */
    181     public function getActiveValidators($attribute = null)
    182     {
    183         $validators = [];
    184         $scenario = $this->getScenario();
    185         foreach ($this->getValidators() as $validator) {
    186             if ($validator->isActive($scenario) && ($attribute === null || in_array($attribute, $validator->attributes, true))) {
    187                 $validators[] = $validator;
    188             }
    189         }
    190         return $validators;
    191     }
    192 
    193     /**
    194      * Creates validator objects based on the validation rules specified in [[rules()]].
    195      * Unlike [[getValidators()]], each time this method is called, a new list of validators will be returned.
    196      * @return ArrayObject validators
    197      * @throws InvalidConfigException if any validation rule configuration is invalid
    198      */
    199     public function createValidators()
    200     {
    201         $validators = new ArrayObject;
    202         foreach ($this->rules() as $rule) {
    203             if ($rule instanceof Validator) {
    204                 $validators->append($rule);
    205             } elseif (is_array($rule) && isset($rule[0], $rule[1])) { // attributes, validator type
    206                 $validator = Validator::createValidator($rule[1], $this, (array) $rule[0], array_slice($rule, 2));
    207                 $validators->append($validator);
    208             } else {
    209                 throw new InvalidConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.');
    210             }
    211         }
    212         return $validators;
    213     }
    214 
    215     /**
    216      * Returns a value indicating whether the attribute is required.
    217      * This is determined by checking if the attribute is associated with a
    218      * [[yiivalidatorsRequiredValidator|required]] validation rule in the
    219      * current [[scenario]].
    220      *
    221      * Note that when the validator has a conditional validation applied using
    222      * [[yiivalidatorsRequiredValidator::$when|$when]] this method will return
    223      * `false` regardless of the `when` condition because it may be called be
    224      * before the model is loaded with data.
    225      *
    226      * @param string $attribute attribute name
    227      * @return boolean whether the attribute is required
    228      */
    229     public function isAttributeRequired($attribute)
    230     {
    231         foreach ($this->getActiveValidators($attribute) as $validator) {
    232             if ($validator instanceof RequiredValidator && $validator->when === null) {
    233                 return true;
    234             }
    235         }
    236         return false;
    237     }
    238 
    239     /**
    240      * Returns a value indicating whether the attribute is safe for massive assignments.
    241      * @param string $attribute attribute name
    242      * @return boolean whether the attribute is safe for massive assignments
    243      * @see safeAttributes()
    244      */
    245     public function isAttributeSafe($attribute)
    246     {
    247         return in_array($attribute, $this->safeAttributes(), true);
    248     }
    249 
    250     /**
    251      * Returns a value indicating whether the attribute is active in the current scenario.
    252      * @param string $attribute attribute name
    253      * @return boolean whether the attribute is active in the current scenario
    254      * @see activeAttributes()
    255      */
    256     public function isAttributeActive($attribute)
    257     {
    258         return in_array($attribute, $this->activeAttributes(), true);
    259     }
    260 
    261     /**
    262      * Returns the text label for the specified attribute.
    263      * @param string $attribute the attribute name
    264      * @return string the attribute label
    265      * @see generateAttributeLabel()
    266      * @see attributeLabels()
    267      */
    268     public function getAttributeLabel($attribute)
    269     {
    270         $labels = $this->attributeLabels();
    271         return isset($labels[$attribute]) ? $labels[$attribute] : $this->generateAttributeLabel($attribute);
    272     }
    273 
    274     /**
    275      * Returns a value indicating whether there is any validation error.
    276      * @param string|null $attribute attribute name. Use null to check all attributes.
    277      * @return boolean whether there is any error.
    278      */
    279     public function hasErrors($attribute = null)
    280     {
    281         return $attribute === null ? !empty($this->_errors) : isset($this->_errors[$attribute]);
    282     }
    283 
    284     /**
    285      * Returns the errors for all attribute or a single attribute.
    286      * @param string $attribute attribute name. Use null to retrieve errors for all attributes.
    287      * @property array An array of errors for all attributes. Empty array is returned if no error.
    288      * The result is a two-dimensional array. See [[getErrors()]] for detailed description.
    289      * @return array errors for all attributes or the specified attribute. Empty array is returned if no error.
    290      * Note that when returning errors for all attributes, the result is a two-dimensional array, like the following:
    291      *
    292      * ~~~
    293      * [
    294      *     'username' => [
    295      *         'Username is required.',
    296      *         'Username must contain only word characters.',
    297      *     ],
    298      *     'email' => [
    299      *         'Email address is invalid.',
    300      *     ]
    301      * ]
    302      * ~~~
    303      *
    304      * @see getFirstErrors()
    305      * @see getFirstError()
    306      */
    307     public function getErrors($attribute = null)
    308     {
    309         if ($attribute === null) {
    310             return $this->_errors === null ? [] : $this->_errors;
    311         } else {
    312             return isset($this->_errors[$attribute]) ? $this->_errors[$attribute] : [];
    313         }
    314     }
    315 
    316     /**
    317      * Returns the first error of every attribute in the model.
    318      * @return array the first errors. The array keys are the attribute names, and the array
    319      * values are the corresponding error messages. An empty array will be returned if there is no error.
    320      * @see getErrors()
    321      * @see getFirstError()
    322      */
    323     public function getFirstErrors()
    324     {
    325         if (empty($this->_errors)) {
    326             return [];
    327         } else {
    328             $errors = [];
    329             foreach ($this->_errors as $name => $es) {
    330                 if (!empty($es)) {
    331                     $errors[$name] = reset($es);
    332                 }
    333             }
    334 
    335             return $errors;
    336         }
    337     }
    338 
    339     /**
    340      * Returns the first error of the specified attribute.
    341      * @param string $attribute attribute name.
    342      * @return string the error message. Null is returned if no error.
    343      * @see getErrors()
    344      * @see getFirstErrors()
    345      */
    346     public function getFirstError($attribute)
    347     {
    348         return isset($this->_errors[$attribute]) ? reset($this->_errors[$attribute]) : null;
    349     }
    350 
    351     /**
    352      * Adds a new error to the specified attribute.
    353      * @param string $attribute attribute name
    354      * @param string $error new error message
    355      */
    356     public function addError($attribute, $error = '')
    357     {
    358         $this->_errors[$attribute][] = $error;
    359     }
    360 
    361     /**
    362      * Adds a list of errors.
    363      * @param array $items a list of errors. The array keys must be attribute names.
    364      * The array values should be error messages. If an attribute has multiple errors,
    365      * these errors must be given in terms of an array.
    366      * You may use the result of [[getErrors()]] as the value for this parameter.
    367      * @since 2.0.2
    368      */
    369     public function addErrors(array $items)
    370     {
    371         foreach ($items as $attribute => $errors) {
    372             if (is_array($errors)) {
    373                 foreach ($errors as $error) {
    374                     $this->addError($attribute, $error);
    375                 }
    376             } else {
    377                 $this->addError($attribute, $errors);
    378             }
    379         }
    380     }
    381 
    382     /**
    383      * Removes errors for all attributes or a single attribute.
    384      * @param string $attribute attribute name. Use null to remove errors for all attribute.
    385      */
    386     public function clearErrors($attribute = null)
    387     {
    388         if ($attribute === null) {
    389             $this->_errors = [];
    390         } else {
    391             unset($this->_errors[$attribute]);
    392         }
    393     }
    394 
    395     /**
    396      * Generates a user friendly attribute label based on the give attribute name.
    397      * This is done by replacing underscores, dashes and dots with blanks and
    398      * changing the first letter of each word to upper case.
    399      * For example, 'department_name' or 'DepartmentName' will generate 'Department Name'.
    400      * @param string $name the column name
    401      * @return string the attribute label
    402      */
    403     public function generateAttributeLabel($name)
    404     {
    405         return Inflector::camel2words($name, true);
    406     }
    407 
    408     /**
    409      * Returns attribute values.
    410      * @param array $names list of attributes whose value needs to be returned.
    411      * Defaults to null, meaning all attributes listed in [[attributes()]] will be returned.
    412      * If it is an array, only the attributes in the array will be returned.
    413      * @param array $except list of attributes whose value should NOT be returned.
    414      * @return array attribute values (name => value).
    415      */
    416     public function getAttributes($names = null, $except = [])
    417     {
    418         $values = [];
    419         if ($names === null) {
    420             $names = $this->attributes();
    421         }
    422         foreach ($names as $name) {
    423             $values[$name] = $this->$name;
    424         }
    425         foreach ($except as $name) {
    426             unset($values[$name]);
    427         }
    428 
    429         return $values;
    430     }
    431 
    432     /**
    433      * Sets the attribute values in a massive way.
    434      * @param array $values attribute values (name => value) to be assigned to the model.
    435      * @param boolean $safeOnly whether the assignments should only be done to the safe attributes.
    436      * A safe attribute is one that is associated with a validation rule in the current [[scenario]].
    437      * @see safeAttributes()
    438      * @see attributes()
    439      */
    440     public function setAttributes($values, $safeOnly = true)
    441     {
    442         // 必须是个数组
    443         if (is_array($values)) {
    444             // array_flip — 交换数组中的键和值
    445             // 将属性放到了 key 上
    446             // 默认取 safeAttributes 中的属性
    447             $attributes = array_flip($safeOnly ? $this->safeAttributes() : $this->attributes());
    448             foreach ($values as $name => $value) {
    449                 if (isset($attributes[$name])) {
    450                     // 如果存在该属性,就直接赋值
    451                     $this->$name = $value;
    452                 } elseif ($safeOnly) {
    453                     // 如果不存在,而且是 safeOnly 的话,就触发一下 onUnsafeAttribute 方法
    454                     $this->onUnsafeAttribute($name, $value);
    455                 }
    456             }
    457         }
    458     }
    459 
    460     /**
    461      * This method is invoked when an unsafe attribute is being massively assigned.
    462      * The default implementation will log a warning message if YII_DEBUG is on.
    463      * It does nothing otherwise.
    464      * @param string $name the unsafe attribute name
    465      * @param mixed $value the attribute value
    466      */
    467     public function onUnsafeAttribute($name, $value)
    468     {
    469         if (YII_DEBUG) {
    470             // 如果是调试状态,就打 log 记录下,没有成功设置的不安全的属性
    471             Yii::trace("Failed to set unsafe attribute '$name' in '" . get_class($this) . "'.", __METHOD__);
    472         }
    473     }
    474 
    475     /**
    476      * Returns the scenario that this model is used in.
    477      *
    478      * Scenario affects how validation is performed and which attributes can
    479      * be massively assigned.
    480      *
    481      * @return string the scenario that this model is in. Defaults to [[SCENARIO_DEFAULT]].
    482      */
    483     public function getScenario()
    484     {
    485         // 获取当前的场景
    486         return $this->_scenario;
    487     }
    488 
    489     /**
    490      * Sets the scenario for the model.
    491      * Note that this method does not check if the scenario exists or not.
    492      * The method [[validate()]] will perform this check.
    493      * @param string $value the scenario that this model is in.
    494      */
    495     public function setScenario($value)
    496     {
    497         // 设置当前的场景
    498         $this->_scenario = $value;
    499     }
    500 
    501     /**
    502      * Returns the attribute names that are safe to be massively assigned in the current scenario.
    503      * @return string[] safe attribute names
    504      */
    505     public function safeAttributes()
    506     {
    507         // 获取当前的场景
    508         $scenario = $this->getScenario();
    509         // 获取所有场景及其属性
    510         $scenarios = $this->scenarios();
    511         if (!isset($scenarios[$scenario])) {
    512             // 场景不存在,就返回空
    513             return [];
    514         }
    515         $attributes = [];
    516         foreach ($scenarios[$scenario] as $attribute) {
    517             // 将开头不是!的属性才会放入到 safeAttributes 中, 即以!开头的属性不会被放到 safeAttributes 中
    518             if ($attribute[0] !== '!') {
    519                 $attributes[] = $attribute;
    520             }
    521         }
    522 
    523         return $attributes;
    524     }
    525 
    526     /**
    527      * Returns the attribute names that are subject to validation in the current scenario.
    528      * @return string[] safe attribute names
    529      */
    530     public function activeAttributes()
    531     {
    532         // 同上
    533         $scenario = $this->getScenario();
    534         $scenarios = $this->scenarios();
    535         if (!isset($scenarios[$scenario])) {
    536             return [];
    537         }
    538         // 获取当前场景中的所有属性
    539         $attributes = $scenarios[$scenario];
    540         foreach ($attributes as $i => $attribute) {
    541             // 如果属性名以!开头,就把!截取掉
    542             // !开头的属性来自rules,加!能够使规则(即 validator)生效,但却能够不出现在 safeAttributes 中
    543             if ($attribute[0] === '!') {
    544                 $attributes[$i] = substr($attribute, 1);
    545             }
    546         }
    547 
    548         return $attributes;
    549     }
    550 
    551     /**
    552      * Populates the model with the data from end user.
    553      * The data to be loaded is `$data[formName]`, where `formName` refers to the value of [[formName()]].
    554      * If [[formName()]] is empty, the whole `$data` array will be used to populate the model.
    555      * The data being populated is subject to the safety check by [[setAttributes()]].
    556      * 加载数据到所在的 model 中
    557      * @param array $data the data array. This is usually `$_POST` or `$_GET`, but can also be any valid array
    558      * supplied by end user.
    559      * @param string $formName the form name to be used for loading the data into the model.
    560      * If not set, [[formName()]] will be used.
    561      * @return boolean whether the model is successfully populated with some data.
    562      */
    563     public function load($data, $formName = null)
    564     {
    565         // 如果存在 yii 的 form,就使用该 form,否则就拿到所在类的名称(不含 namespace)
    566         $scope = $formName === null ? $this->formName() : $formName;
    567         if ($scope === '' && !empty($data)) {
    568             // 如果 $scope 为空字符串,且 $data不为空,就设置属性
    569             // 即 $formName 为空字符串,且 $data不为空
    570             $this->setAttributes($data);
    571 
    572             return true;
    573         } elseif (isset($data[$scope])) {
    574             // 否则,必须存在 $data[$scope],使用 $data[$scope] 去设置属性
    575             $this->setAttributes($data[$scope]);
    576 
    577             return true;
    578         } else {
    579             return false;
    580         }
    581     }
    582 
    583     /**
    584      * Populates a set of models with the data from end user.
    585      * 加载数据到所在的 model 的集合中
    586      * This method is mainly used to collect tabular data input.
    587      * The data to be loaded for each model is `$data[formName][index]`, where `formName`
    588      * refers to the value of [[formName()]], and `index` the index of the model in the `$models` array.
    589      * If [[formName()]] is empty, `$data[index]` will be used to populate each model.
    590      * The data being populated to each model is subject to the safety check by [[setAttributes()]].
    591      * @param array $models the models to be populated. Note that all models should have the same class.
    592      * @param array $data the data array. This is usually `$_POST` or `$_GET`, but can also be any valid array
    593      * supplied by end user.
    594      * @param string $formName the form name to be used for loading the data into the models.
    595      * If not set, it will use the [[formName()]] value of the first model in `$models`.
    596      * This parameter is available since version 2.0.1.
    597      * @return boolean whether at least one of the models is successfully populated.
    598      */
    599     public static function loadMultiple($models, $data, $formName = null)
    600     {
    601         if ($formName === null) {
    602             /* @var $first Model */
    603             // reset — 将数组的内部指针指向第一个单元
    604             $first = reset($models);
    605             if ($first === false) {
    606                 // 不存在就返回 false
    607                 return false;
    608             }
    609             // 拿到所在类的名称(不含 namespace)
    610             $formName = $first->formName();
    611         }
    612 
    613         $success = false;
    614         // 遍历 $models,一个个 load 数据
    615         foreach ($models as $i => $model) {
    616             /* @var $model Model */
    617             if ($formName == '') {
    618                 if (!empty($data[$i])) {
    619                     // 数据不为空,就 load 到相应的 model 中
    620                     $model->load($data[$i], '');
    621                     $success = true;
    622                 }
    623             } elseif (!empty($data[$formName][$i])) {
    624                 // 存在 $formName,且数据不为空,就 load 到相应的 model 中
    625                 $model->load($data[$formName][$i], '');
    626                 $success = true;
    627             }
    628         }
    629 
    630         return $success;
    631     }
    632 
    633     /**
    634      * Validates multiple models.
    635      * This method will validate every model. The models being validated may
    636      * be of the same or different types.
    637      * @param array $models the models to be validated
    638      * @param array $attributeNames list of attribute names that should be validated.
    639      * If this parameter is empty, it means any attribute listed in the applicable
    640      * validation rules should be validated.
    641      * @return boolean whether all models are valid. False will be returned if one
    642      * or multiple models have validation error.
    643      */
    644     public static function validateMultiple($models, $attributeNames = null)
    645     {
    646         $valid = true;
    647         /* @var $model Model */
    648         foreach ($models as $model) {
    649             //遍历$models 调用validate()方法
    650             $valid = $model->validate($attributeNames) && $valid;
    651         }
    652 
    653         return $valid;
    654     }
    655 
    656     /**
    657      * Returns the list of fields that should be returned by default by [[toArray()]] when no specific fields are specified.
    658      * 以数组形式返回定义的一个字段名或字段
    659      * A field is a named element in the returned array by [[toArray()]].
    660      * 
    661      * This method should return an array of field names or field definitions.
    662      *  此方法应该返回一个字段名或字段定义的数组
    663      * If the former, the field name will be treated as an object property name whose value will be used
    664      * as the field value. If the latter, the array key should be the field name while the array value should be
    665      * the corresponding field definition which can be either an object property name or a PHP callable
    666      * returning the corresponding field value. The signature of the callable should be:
    667      * 如果前者,该字段名将被视为一个对象属性名,其值将用作该字段值。
    668      * 如果是后者,数组的键应该是字段名称,数组的值应相应的字段定义可以是一个对象的属性名称或PHP回调函数
    669      * ```php
    670      * function ($field, $model) {
    671      *     // return field value
    672      * }
    673      * ```
    674      *
    675      * For example, the following code declares four fields:
    676      *
    677      * - `email`: the field name is the same as the property name `email`;
    678      * - `firstName` and `lastName`: the field names are `firstName` and `lastName`, and their
    679      *   values are obtained from the `first_name` and `last_name` properties;
    680      * - `fullName`: the field name is `fullName`. Its value is obtained by concatenating `first_name`
    681      *   and `last_name`.
    682      *
    683      * ```php
    684      * return [
    685      *     'email',
    686      *     'firstName' => 'first_name',
    687      *     'lastName' => 'last_name',
    688      *     'fullName' => function ($model) {
    689      *         return $model->first_name . ' ' . $model->last_name;
    690      *     },
    691      * ];
    692      * ```
    693      *
    694      * In this method, you may also want to return different lists of fields based on some context
    695      * information. For example, depending on [[scenario]] or the privilege of the current application user,
    696      * you may return different sets of visible fields or filter out some fields.
    697      * 在这个方法中,可能还希望在根据条件返回不同的字段列表,例如,根据[[scenario]]或者当前应用程序用户的权限
    698      * 设置不同的可见字段或者过滤某些字段
    699      * The default implementation of this method returns [[attributes()]] indexed by the same attribute names.
    700      * 默认返回[[attributes()]]中的属性名为索引的所有字段
    701      * @return array the list of field names or field definitions.
    702      * @see toArray()
    703      */
    704     public function fields()
    705     {
    706         $fields = $this->attributes();
    707         // array_combine — 创建一个数组,用一个数组的值作为其键名,另一个数组的值作为其值
    708         return array_combine($fields, $fields);
    709     }
    710 
    711     /**
    712      * Returns an iterator for traversing the attributes in the model.
    713      * This method is required by the interface IteratorAggregate.
    714      * @return ArrayIterator an iterator for traversing the items in the list.
    715      */
    716     public function getIterator()
    717     {
    718         // 获取该 model 的所有属性
    719         $attributes = $this->getAttributes();
    720         // ArrayIterator 这个迭代器允许在遍历数组和对象时删除和更新值与键
    721         // 当你想多次遍历相同数组时你需要实例化 ArrayObject,然后让这个实例创建一个 ArrayIteratror 实例, 然后使用 foreach 或者 手动调用 getIterator() 方法
    722         return new ArrayIterator($attributes);
    723     }
    724 
    725     /**
    726      * Returns whether there is an element at the specified offset.
    727      * This method is required by the SPL interface `ArrayAccess`.
    728      * It is implicitly called when you use something like `isset($model[$offset])`.
    729      * @param mixed $offset the offset to check on
    730      * @return boolean
    731      */
    732     public function offsetExists($offset)
    733     {
    734         // 将 isset($model[$offset]) 重写为 isset($model->$offset)
    735         return $this->$offset !== null;
    736     }
    737 
    738     /**
    739      * Returns the element at the specified offset.
    740      * This method is required by the SPL interface `ArrayAccess`.
    741      * It is implicitly called when you use something like `$value = $model[$offset];`.
    742      * @param mixed $offset the offset to retrieve element.
    743      * @return mixed the element at the offset, null if no element is found at the offset
    744      */
    745     public function offsetGet($offset)
    746     {
    747         // 将获取 $model[$offset] 重写为 $model->$offset
    748         return $this->$offset;
    749     }
    750 
    751     /**
    752      * Sets the element at the specified offset.
    753      * This method is required by the SPL interface `ArrayAccess`.
    754      * It is implicitly called when you use something like `$model[$offset] = $item;`.
    755      * @param integer $offset the offset to set element
    756      * @param mixed $item the element value
    757      */
    758     public function offsetSet($offset, $item)
    759     {
    760         // 将 $model[$offset] = $item 重写为 $model->$offset = $item
    761         $this->$offset = $item;
    762     }
    763 
    764     /**
    765      * Sets the element value at the specified offset to null.
    766      * This method is required by the SPL interface `ArrayAccess`.
    767      * It is implicitly called when you use something like `unset($model[$offset])`.
    768      * @param mixed $offset the offset to unset element
    769      */
    770     public function offsetUnset($offset)
    771     {
    772         // 将 unset($model[$offset]) 重写为 $model->$offset = null
    773         $this->$offset = null;
    774     }
  • 相关阅读:
    海思HI3516A开发板顺利上线
    android WIFI信息获取
    五------Jsp九大内置对象。
    在Windows下搭建Apacheserver
    基于ContentObserver来动态取消或加入屏幕超时任务
    使用Intent的Flag设置启动參数
    IntelliJ IDEA像Eclipse一样打开多个项目
    怎样让IE支持自己定义协议
    《TCP/IP具体解释卷2:实现》笔记--协议控制块
    POJ2029:Get Many Persimmon Trees(二维树状数组)
  • 原文地址:https://www.cnblogs.com/dragon16/p/5535878.html
Copyright © 2011-2022 走看看