第一步:数据发送到后台后,通过 $data = YII::$app->request->post() (假如是post请求)
$model = new User();
调用$model->load()把接受的数据 $data 载入对象中
第二步:
看load方法 (vendor\yiisoft\yii2\base\Model.php)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public function load($data, $formName = null) { $scope = $formName === null ? $this->formName() : $formName; if ($scope === '' && !empty($data)) { $this->setAttributes($data); return true; } elseif (isset($data[$scope])) { $this->setAttributes($data[$scope]); return true; } return false; } |
第三步:
其中$data是我们第一步中传入的数据($data);$formName 是表单的name
1.当$formName 为空时 通过$this->formName() 获取
看formName()方法:
1 2 3 4 5 | public function formName() { $reflector = new ReflectionClass($this); return $reflector->getShortName(); } |
该方法通过反射获取到当前模型的名称(不带命名空间)
第四步:
如果$data 中存在 $scope 作为键值的数据,则 调用$this->setAttributes($data);否则返回false (也就是载入失败)
第五步:
看 $this->setAttributes($data)
1 2 3 4 5 6 7 8 9 10 11 12 13 | public function setAttributes($values, $safeOnly = true) { if (is_array($values)) { $attributes = array_flip($safeOnly ? $this->safeAttributes() : $this->attributes()); foreach ($values as $name => $value) { if (isset($attributes[$name])) { $this->$name = $value; } elseif ($safeOnly) { $this->onUnsafeAttribute($name, $value); } } } } |
从第四步可以看出,$safeOnly使用的是默认值 true;
此时如果$data是一个字符串,那么返回也是载入成功,其实模型($model)并没有做改变
如果$data是一个非空数组 ,将进一步获取$attributes,因为$safeOnly是true 所以三元运算符走 $this->safeAttributes()
看:$this->safeAttributes()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public function safeAttributes() { $scenario = $this->getScenario(); $scenarios = $this->scenarios(); if (!isset($scenarios[$scenario])) { return []; } $attributes = []; foreach ($scenarios[$scenario] as $attribute) { if ($attribute[0] !== '!' && !in_array('!' . $attribute, $scenarios[$scenario])) { $attributes[] = $attribute; } } return $attributes; } |
$scenario = $this->getScenario(); //获取到当前场景
$scenarios = $this->scenarios(); //获取所有场景 ,每一个场景中包含的是rules中的字段 ,这也就是为啥没有设置的时候无法载入的问题
看一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | public function scenarios() { $scenarios = [self::SCENARIO_DEFAULT => []]; foreach ($this->getValidators() as $validator) { 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)) { foreach ($names as $name) { foreach ($validator->attributes as $attribute) { $scenarios[$name][$attribute] = true; } } } elseif (empty($validator->on)) { foreach ($names as $name) { if (!in_array($name, $validator->except, true)) { foreach ($validator->attributes as $attribute) { $scenarios[$name][$attribute] = true; } } } } else { foreach ($validator->on as $name) { foreach ($validator->attributes as $attribute) { $scenarios[$name][$attribute] = true; } } } } foreach ($scenarios as $scenario => $attributes) { if (!empty($attributes)) { $scenarios[$scenario] = array_keys($attributes); } } return $scenarios; } |
通过跟踪 $this->getValidators() 找到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public function createValidators() { $validators = new ArrayObject; foreach ($this->rules() as $rule) { if ($rule instanceof Validator) { $validators->append($rule); } elseif (is_array($rule) && isset($rule[0], $rule[1])) { // attributes, validator type $validator = Validator::createValidator($rule[1], $this, (array) $rule[0], array_slice($rule, 2)); $validators->append($validator); } else { throw new InvalidConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.'); } } return $validators; } |
而:$this->rules() 返回的就是当前实例化的模型中 rules 方法
解决方法:
1.在rules中声明需要载入的字段
2.载入后用$this->字段=值
未经允许不得转载:开心乐窝-乐在其中 » yii2 load 时不加载非验证字段