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