Laravel自定义唯一验证下如何实现数据更新?
嘿,我明白你遇到的问题了——更新操作时这条自定义唯一验证总是报错,对吧?这是因为你的规则没考虑到「要排除当前正在更新的这条记录」,导致系统把它当成重复数据了。咱们一步步来修复:
先分析问题根源
当你更新一条子菜单记录时,数据库里本来就存在一条「menu_id等于当前请求值、title等于当前请求值」的记录——就是你正在编辑的这条!而你现在的自定义规则只会无脑检查这个组合是否存在,自然会返回验证失败。
方案一:修复你的自定义验证规则
我们给规则加上「排除指定ID」的逻辑,让它在更新时跳过当前记录:
Validator::extend('unique_custom', function ($attribute, $value, $parameters) { // 参数顺序调整为:表名, 要验证的字段, 关联字段名, 关联字段值, [排除字段名, 排除ID值] list($table, $field, $field2, $field2Value) = $parameters; // 基础查询:检查title和menu_id的组合 $query = \DB::table($table)->where($field, $value)->where($field2, $field2Value); // 如果传入了排除ID的参数,就跳过当前记录 if (isset($parameters[4]) && isset($parameters[5])) { $query->where($parameters[4], '!=', $parameters[5]); } return $query->count() == 0; });
然后在更新方法里,传入当前要更新的记录ID(假设你的子菜单表主键是id,且通过路由模型绑定拿到了实例):
public function updateSubmenu(Request $request, \App\Models\Submenu $submenu) { $this->validate($request, [ 'menu_id' => 'required', // 最后两个参数:排除的字段名(id)、当前记录的ID 'title' => 'required|unique_custom:submenus,title,menu_id,'.$request->menu_id.',id,'.$submenu->id, 'order_by' => 'required|integer', 'description' => 'required' ], [ 'title.unique_custom' => '这个标题已经被占用了哦' ]); // 执行更新逻辑 $submenu->fill($request->all())->save(); return redirect()->back()->with('success', '子菜单更新成功'); }
方案二:用Laravel自带的规则(更推荐!)
其实Laravel原生的unique规则就支持组合唯一+排除当前记录的场景,不用自己写自定义规则,更符合框架最佳实践:
public function updateSubmenu(Request $request, \App\Models\Submenu $submenu) { $this->validate($request, [ 'menu_id' => 'required', 'title' => [ 'required', \Illuminate\Validation\Rule::unique('submenus') ->where('menu_id', $request->menu_id) // 关联menu_id的条件 ->ignore($submenu->id) // 排除当前记录 ], 'order_by' => 'required|integer', 'description' => 'required' ], [ 'title.unique' => '这个标题已经被占用了哦' ]); // 执行更新逻辑 $submenu->fill($request->all())->save(); return redirect()->back()->with('success', '子菜单更新成功'); }
这个写法更简洁,后续Laravel版本更新也不用维护自定义规则,建议优先用这个方案~
内容的提问来源于stack exchange,提问作者Sky
相关产品推荐
相关产品推荐

