You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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` <> 

解决方案

问题根源在唯一性验证规则的写法:

  1. CategoryDetails模型指定了主键为category_id,但Laravel默认的unique规则会用id作为排除字段,而你的表中没有id字段,因此报错。
  2. $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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 06:15:34