场景还原UserModelclass UserModel extends Model { public function role() { return $this->belognsTo(RoleModel::class , ‘role_id’ , ‘id’); }}出错的程序$user = UserModel::with(‘role’)->find(1);// $user->role 是一个 RoleModel// 更新 role 属性$user->role = ’test’;// 正确输出 testvar_dump($user->role);// 但是!!转换成 json 字符串后// 你会发现,role 居然还是个模型!!// 并不是你后面设置成的 test !// 怪胎,丢失更新了?Laravel Bug ??// 实际上不是!请看下属描述var_dump(json_encode($user));原理概述Laravel 的 Illuminate\Database\Eloquent\Model 实现了 JsonSerializable 接口,所以在调用 json_encode 进行序列化时,会调用 Model::jsonSerialize 方法,他这个方法返回的数据是:array_merge($attribute , $relation);实际上你通过:$model->name = ‘grayVTouch’;这种方式附加的新属性,Laravel 通过 __set 魔术方法重载,将其添加到 attribute 数组中,你是无法更改 relation 数组的!而通过 模型关联 你却可以为 relation 数组新增单元!看到上面的数组合并方式,可以知道 relation 会覆盖掉 attribute 中的同名属性!!因而要特别注意:如果 relation 中有和 attribute 中同名的属性,请修改 relation 关联名称!如果不想修改 relation 名称,坚持前者覆盖后者,请:// 保存值$attr = $model->attr;// 删除属性:attribute / relation 中的属性(Laravel 内部调用 __unset 魔术方法)unset($model->attr)// 重新设置值,仅设置到 attribute 数组// relation 并不会被设置$model->attr = $model;综合评价Laravel 由于将模型属性拆分成两个数组,而他们实际上又同属于一个对象!所以如果存在同名属性,必然会产生 谁覆盖谁 的问题,attribute 一开始就是对应数据库表中的字段的,而 relation 是后面程序附加的,为了不丢失更新,后者覆盖前者,非常正确。虽然在使用过程中应该小心避免 relation 和 attribute 撞上同名属性,但偶尔还是会碰到的~,这个还是稍微注意下就好,这并非 Bug,而是在当前的程序处理方式下必然会产生的一个正常现象。