Laravel操作Mongo报错:间接修改重载属性App\Dossier::$program无效
解决Laravel中Mongo嵌套属性间接修改无效的问题
嘿,这个问题我之前也碰到过!你遇到的Indirect modification of overloaded property App\Dossier::$program has no effect错误,本质是因为Eloquent模型的嵌套属性是通过魔术方法重载加载的,直接修改它的嵌套元素不会被模型追踪到变化,所以save()的时候根本没生效,还抛出了这个错误。
问题代码回顾
你原本的代码是直接修改嵌套属性:
$dossier = Dossier::where('_id', (int)$request->input('dossier_id'))->first(); $dossier->program[$request->input('program')]['cities'][$request->input('city')]['services'][$request->input('service')][$request->input('name')] = $request->input('value'); $dossier->save();
修正方案
我们需要先把嵌套属性取出到临时变量,修改后再重新赋值给模型,这样Laravel才能识别到属性变化:
$dossier = Dossier::where('_id', (int)$request->input('dossier_id'))->first(); // 1. 把program属性取出到临时变量 $program = $dossier->program; // 2. 修改临时变量里的嵌套值 $program[$request->input('program')]['cities'][$request->input('city')]['services'][$request->input('service')][$request->input('name')] = $request->input('value'); // 3. 重新赋值给模型属性 $dossier->program = $program; // 4. 保存模型 $dossier->save();
或者也可以使用setAttribute方法来显式设置属性,效果是一样的:
$dossier = Dossier::where('_id', (int)$request->input('dossier_id'))->first(); $program = $dossier->program; $program[$request->input('program')]['cities'][$request->input('city')]['services'][$request->input('service')][$request->input('name')] = $request->input('value'); $dossier->setAttribute('program', $program); $dossier->save();
原理说明
当你直接访问$dossier->program时,Eloquent通过__get魔术方法动态加载这个属性,它并不是模型的直接成员变量。直接修改它的嵌套元素属于“间接修改重载属性”,模型的属性变更追踪机制不会感知到这个变化,自然不会在save()时同步到MongoDB。而先取出到临时变量修改,再重新赋值,会触发模型的属性变更检测,这样就能正确保存修改后的内容了。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

