常见误区 - load数据失败

  • 作者:KK

  • 发表日期:2017.4.12


复述一下load

如果根据官方教程用ActiveForm构造前端表单,再提交数据到后端,基于这种场合我先示例一下平时load的过程:

$post = Yii::$app->request->post();
/*
实际上此时的结构如下:
$post = [
	'UserForm' => [
		'name' => 'aaa',
		'age' => 11,
	]
]
*/

$model = new UserForm();
$model->load($post);

echo $model->name; //aaa
echo $model->age; //11

其中要注意$post数据的结构,name和age外面还有一层叫UserForm的key,这个key和模型的名称是一模一样的,这个key也是ActiveForm根据模型名称生成出来的


load方法的简化版

接下来我来写一个load方法的简单版,你看看代码估计就很快明白load干哪些事了

namespace yii\base;

class Model{
	public function load($data, $modelName = null){
		if($modelName === null){
			//如果没有指定模型名字
			$reflector = new ReflectionClass($this);
			//得到短类名,比如类名是 app\models\UserForm 那就是得到 UserForm 这一部分
			$modelName = $reflector->getShortName();
		}
		
		if($modelName === ''){
			//如果指定了为空字符串,直接把key当属性名赋值value套到自己的属性里
			foreach($data as $key => $value){
				$this->{$key} = $value;
			}
			return true;
			
		}elseif(isset($data[$modelName])){
			//如果模型名字比如 UserForm 这个key在data里的话,那就遍历这个key下面的属性进行赋值
			foreach($data[$modelName] as $key => $value){
				$this->{$key} = $value;
			}
			return true;
		}else{
			return false;
		}
	}
}

自定义表单要load成功通常得传第2个参数为空字符串

很经常大家都是自己构造表单的,毕竟ActiveForm满足不了各种需求,甚至一些ajax的前端数据构造逻辑更加直接,前端人员想都没想到要加模型名字包一层对象

现象大概就是这样的:

$post = [
	'name' => 'aaa',
	'age' => 11,
];

$model = new UserForm();
$model->load($post);

根据上面的解析,如果第2个参数为默认的null,则load里面会自动获取模型的短类名得到UserForm,然后企图从$data['UserForm']里取得要被load的数据

结果实际上传进去的$post数组在第1层key并不包含UserForm,结果就导致了load失败

在这种情况下要让load的时候直接取$post的key套到模型的属性里,那很简单,就是传入第二个参数为空字符串,一定要是空字符串:

$post = [
	'name' => 'aaa',
	'age' => 11,
];

$model = new UserForm();

$model->load($post, ''); //!!!重点!!!

load失败后是不会有error的

所以如果企图在load返回false的时候打印$model->errors那是不会有东西的

load失败代表的就是这个过程中它无法从$data参数中得到任何可以load的数据,所以如果此时要向客户端报错,我觉得大概应该将提示信息人工设置为“接收参数失败”

有兴趣的话请稳步到此阅读《正确地设定load失败的提示信息