控制器try-catch未捕获模型缺失可填充属性的错误,如何捕获此类问题?
控制器try-catch未捕获模型缺失可填充属性的错误,如何捕获此类问题?
这个问题我之前也踩过坑!核心原因是Laravel默认对批量赋值时的无效属性会静默忽略,不会抛出任何异常,所以你的try-catch块自然抓不到这类问题。下面给你几个实用的解决方案:
1. 开启模型严格模式(最推荐的开发阶段方案)
在你的Bundle模型里添加$strict = true;属性,这样当你尝试给不在$fillable(或在$guarded里)的字段赋值时,Laravel会直接抛出MassAssignmentException异常,这时候你的try-catch就能正常捕获了。
修改后的模型代码:
class Bundle extends Model { protected $fillable = [ 'name', 'description', 'remarks', 'image_path', // 之前未添加status时 ]; protected $strict = true; // 开启严格模式 }
开启后,当你调用$bundle->update(['status' => false])时,就会触发异常,catch块会捕获到类似Add [status] to fillable property to allow mass assignment on [App\Models\Admin\Services\Bundle].的错误信息,帮你快速定位问题。
2. 手动验证要更新的字段是否在可填充列表中
如果你不想全局开启严格模式,可以在控制器里手动检查要更新的字段是否属于模型的$fillable集合,发现无效字段就主动抛出异常:
public function changeStatus($id) { try { // 用findOrFail代替find,找不到记录时也会抛出异常 $bundle = Bundle::findOrFail($id); $updateData = ['status' => false]; // 获取模型的可填充字段列表 $fillableFields = $bundle->getFillable(); // 找出不在可填充列表中的字段 $invalidFields = array_diff(array_keys($updateData), $fillableFields); if (!empty($invalidFields)) { throw new \Exception('以下字段不允许批量赋值: ' . implode(', ', $invalidFields)); } $bundle->update($updateData); return redirect()->route('admin_bundle.index'); } catch (\Exception $exception) { return response()->json(['status'=>'error', 'error'=> $exception->getMessage()]); } }
3. 使用fill()+save()组合并手动校验
另一种方式是先用fill()方法赋值,然后手动检查属性是否被正确设置(如果没开严格模式的话):
public function changeStatus($id) { try { $bundle = Bundle::findOrFail($id); $bundle->fill(['status' => false]); // 手动检查属性是否被成功赋值 if ($bundle->status !== false) { throw new \Exception('字段status无法被赋值,请检查模型的$fillable配置'); } $bundle->save(); return redirect()->route('admin_bundle.index'); } catch (\Exception $exception) { return response()->json(['status'=>'error', 'error'=> $exception->getMessage()]); } }
补充说明
Laravel默认静默忽略无效批量赋值的设计,是为了安全防范(防止恶意提交未授权的字段),但在开发阶段开启严格模式可以帮你更早发现这类配置错误,建议在本地开发环境开启,生产环境可以根据业务需求决定是否保持开启。
内容来源于stack exchange
相关产品推荐
相关产品推荐

