laravel eloquent orm 默认约定每个数据表都含有一个名为 id 的自增主键。然而,在实际开发中,我们可能需要使用其他列作为主键,例如 pages_id、user_uuid 等。laravel 提供了 $primarykey 属性,允许开发者轻松自定义模型的主键。
要为模型指定一个自定义主键,只需在 Eloquent 模型中声明 protected $primaryKey 属性,并将其设置为你的自定义主键列名。
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Page extends Model { use HasFactory; // 声明自定义主键 protected $primaryKey = 'pages_id'; // 允许批量赋值的字段 protected $fillable = [ 'is_default_home', 'is_default_not_found', 'title', 'slug', 'content', ]; // 其他模型方法... }
通过上述配置,当使用 Page::find($value) 或 Page::where('pages_id', $value)->first() 等方法时,Laravel 将会正确地使用 pages_id 列进行查找。
尽管模型中已正确设置了自定义主键,但在执行数据更新操作时,仍可能遇到如下错误:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'where clause' (SQL: select count(*) as aggregate from `pages` where `slug` = about and `id` <> 3)
这个错误信息清晰地表明,Laravel 在某个查询中仍然试图使用一个名为 id 的列,而你的数据库表中可能并没有这个列,或者它不应该是查询的目标。仔细分析错误中的 SQL 查询语句:select count(*) as aggregate from pages where slug = about and id 3。
这个查询模式是 Laravel 在处理唯一性验证规则时非常常见的。例如,当你尝试更新一个记录的 slug 字段,并且 slug 字段被定义为唯一的,Laravel 会在后台执行一个查询来检查新的 slug 是否已经存在于其他记录中。为了排除当前正在更新的记录本身,unique 规则会默认使用 id 列来过滤。
因此,问题的核心不在于 Page::find($this->modelId)->update($this->modelData()) 这行代码本身(因为它会正确使用 pages_id 进行查找),而在于在此之前执行的数据验证环节,特别是涉及到 unique 规则的验证。
解决此问题的关键在于告诉 Laravel 的唯一性验证规则,在排除当前记录时,应该使用哪个自定义主键列,而不是默认的 id 列。
Laravel 提供了 Illuminate\Validation\Rule 类,允许我们更灵活地定义验证规则。对于 unique 规则,我们可以使用 ignore() 方法来指定排除当前记录,并且可以传递第二个参数来指定用于排除的列名。
假设你在控制器或表单请求中定义了验证规则,并且 slug 字段需要保持唯一性:
<?php namespace App\Http\Controllers; use App\Models\Page; use Illuminate\Http\Request; use Illuminate\Validation\Rule; // 引入 Rule 类 class PageController extends Controller { // ... 其他方法 public function update(Request $request, $modelId) // 假设modelId是pages_id的值 { // 定义验证规则 $request->validate([ 'title' => 'required|string|max:255', 'slug' => [ 'required', 'string', 'max:255', // 关键:使用 Rule::unique() 并指定排除列 // 'pages' 是表名, 'slug' 是要验证唯一性的列 // $modelId 是当前记录的主键值 // 'pages_id' 是你的自定义主键列名 Rule::unique('pages', 'slug')->ignore($modelId, 'pages_id'), ], 'content' => 'nullable|string', 'is_default_home' => 'boolean', 'is_default_not_found' => 'boolean', ]); // 查找并更新记录 $page = Page::find($modelId); // find() 方法会自动使用 $primaryKey 定义的列 if (!$page) { // 处理未找到记录的情况 abort(404); } $page->update([ 'title' => $request->title, 'slug' => $request->slug, 'content' => $request->content, 'is_default_home' => $request->is_default_home, 'is_default_not_found' => $request->is_default_not_found, ]); // ... 其他逻辑 return redirect()->back()->with('success', '页面更新成功!'); } }
在上述示例中,Rule::unique('pages', 'slug')->ignore($modelId, 'pages_id') 是核心所在。
如果你的验证逻辑是在 Livewire 组件中,$this->validate() 方法通常会调用组件内部的 rules() 方法。确保在 rules() 方法中应用相同的 Rule::unique() 模式。
<?php namespace App\Http\Livewire; use Livewire\Component; use App\Models\Page; use Illuminate\Validation\Rule; class PagesCrud extends Component { public $modelId; // 存储当前编辑记录的pages_id public $title, $slug, $content, $isSetToDefaultHomePage, $isSetToDefaultNotFoundPage; // ... 其他属性和方法 public function rules() { return [ 'title' => 'required|string|max:255', 'slug' => [ 'required', 'string', 'max:255', Rule::unique('pages', 'slug')->ignore($this->modelId, 'pages_id'), ], 'content' => 'nullable|string', 'isSetToDefaultHomePage' => 'boolean', 'isSetToDefaultNotFoundPage' => 'boolean', ]; } public function update() { $this->validate(); // 这将触发上面的 rules() 方法 $this->unassignedDefaultHomePage(); $this->unassignedDefaultNotFoundPage(); // 确保 $this->modelId 确实是 pages_id 的值 Page::find($this->modelId)->update($this->modelData()); $this->modalFormVisible = false; $this->reset(); } public function modelData() { return [ 'title' => $this->title, 'slug' => $this->slug, 'content' => $this->content, 'is_default_home' => $this->isSetToDefaultHomePage, 'is_default_not_found' => $this->isSetToDefaultNotFoundPage, ]; } }
在 Laravel 中使用自定义主键时,模型配置 (protected $primaryKey) 是第一步,但并非全部。在进行数据更新操作时,尤其需要注意涉及唯一性验证规则(unique)的场景。通过明确告知 Rule::unique()->ignore() 方法使用正确的自定义主键列进行排除,可以有效解决“未知列'id'”的错误,确保应用程序的稳定运行。理解 Laravel 的默认约定及其提供的灵活性,是解决这类问题的关键。
以上就是Laravel自定义主键:解决更新操作中“未知列'id'”错误的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 //m.sbmmt.com/ All Rights Reserved | php.cn | 湘ICP备2023035733号