Laravel更新分类Slug唯一验证报错:未知列'id'
问题:更新分类时Slug唯一性校验失败
修改现有产品分类数据时遇到问题:分类的slug字段为唯一约束,创建新分类时能正常校验slug是否重复,但更新现有分类时,既会提示slug已被占用,还会抛出数据库字段不存在的错误。
数据库结构
category表
category_id, parent_id, status, created_at, ... --------------------------------------------------
category_details表
category_id, name, slug, description, .... --------------------------------------------------
模型代码
Category 模型
class Category extends Model { use HasFactory; protected $table = "category"; protected $fillable = [ 'parent_id', 'image', 'status', 'show_in_menu', 'sort_order' ]; /** * 关联分类详情表 */ public function details() { return $this->hasOne(CategoryDetails::class, 'category_id', 'id'); } }
CategoryDetails 模型
class CategoryDetails extends Model { use HasFactory; protected $primaryKey = 'category_id'; protected $fillable = [ 'category_id', 'name', 'slug', 'description', 'description_below', 'meta_title', 'meta_description' ]; }
表单请求验证规则
public function rules(): array { if($this->isMethod('post')) { return [ 'name' => 'required', 'slug' => 'required|unique:category_details', 'meta_title' => 'required|max:60', 'meta_description' => 'max:160', 'status' => 'accepted' ]; } if($this->isMethod('patch')) { return [ 'name' => 'required', 'slug' =>'required|unique:category_details,slug,'.$this->category_id, 'meta_title' => 'required|max:60', 'meta_description' => 'max:160', ]; } }
控制器更新方法
public function update(CategoryRequest $request, int $id) { $category = Category::find($id)->first(); $category->update([ 'parent_id' => $request->input('parent_id'), 'image' => '', 'status' => $request->input('status') == 'on' ? 1 : 0, 'sort_order' => $request->input('sort_order') ]); $category->details->update([ 'category_id' => $id, 'name' => $request->input('name'), 'slug' => $request->input('slug'), 'description' => $request->input('description'), 'meta_title' => $request->input('meta_title'), 'meta_description' => $request->input('meta_description') ]); return redirect() ->route('categories.edit', $category->id) ->with('success', "Category {$category->details->name} successfully updated"); }
错误信息
更新时抛出如下错误:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'where clause'
生成的SQL语句:
select count(*) as aggregate from `category_details` where `slug` = dekubitus2 and `id` <>
解决方案
问题根源在唯一性验证规则的写法:
CategoryDetails模型指定了主键为category_id,但Laravel默认的unique规则会用id作为排除字段,而你的表中没有id字段,因此报错。$this->category_id未正确获取到值,导致SQL中出现and id <>的空值情况。
修改表单请求中的patch验证规则,明确指定排除的主键字段:
if($this->isMethod('patch')) { return [ 'name' => 'required', // 明确指定排除的主键字段为category_id,同时通过路由获取正确的分类ID 'slug' => 'required|unique:category_details,slug,'.$this->route('category').',category_id', 'meta_title' => 'required|max:60', 'meta_description' => 'max:160', ]; }
补充说明
$this->route('category')用于获取路由中传递的分类ID(如果你的更新路由参数名为id,则改为$this->route('id'))。- 由于
category_details的主键是category_id,需要在unique规则的第四个参数指定该字段,告诉Laravel排除当前主键对应的记录,而非默认的id。
修改后,更新分类时会正确排除当前分类的slug,既不会出现“已被占用”的误判,也能解决数据库字段不存在的错误。
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

