Laravel API路由模型绑定报错SQLSTATE[42S22]求助
Laravel API路由模型绑定异常解决
问题现象
开发API时,AttendeeController使用Event $event作为方法参数做路由模型绑定,抛出错误:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'event' in 'where clause'
改用string $id手动查询Event模型则能正常运行,希望实现和EventController一致的自动模型解析效果。
相关代码
AttendeeController
<?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Http\Resources\AttendeeResource; use App\Models\Attendee; use App\Models\Event; use Illuminate\Http\Request; class AttendeeController extends Controller { public function index(Event $event) { $attendees = $event->attendees()->latest(); return AttendeeResource::collection($attendees->paginate(10)); } /** * Store a newly created resource in storage. */ public function store(string $id, Request $request) { $event = Event::findOrFail($id); $attendee = $event->attendees()->create([ 'user_id' => 1, ]); return new AttendeeResource($attendee); } /** * Display the specified resource. */ public function show(string $event_id, Attendee $attendee) { return new AttendeeResource($attendee); } /** * Update the specified resource in storage. */ public function update(Request $request, string $id) { // } /** * Remove the specified resource from storage. */ public function destroy(string $id, Attendee $attendee) { $attendee->delete(); return response()->noContent(); } }
EventController
<?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Http\Resources\EventResource; use App\Models\Event; use Illuminate\Http\Request; class EventController extends Controller { /** * Display a listing of the resource. */ // set id as the primary key public function index() { return EventResource::collection(Event::with('user')->paginate(10)); } /** * Store a newly created resource in storage. */ public function store(Request $request) { $event = Event::create([ ...$request->validate([ 'name' => ['required', 'string', 'max:255'], 'description' => ['nullable', 'string', 'max:255'], 'start_date' => ['required', 'date'], 'end_date' => ['required', 'date', 'after:start_date'], ]), 'user_id' => 1, ]); return new EventResource($event); } /** * Display the specified resource. */ public function show(Event $event) { $event->load('user', 'attendees'); return new EventResource($event); } /** * Update the specified resource in storage. */ public function update(Request $request, Event $event) { $request->validate([ 'name' => ['sometimes', 'string', 'max:255'], 'description' => ['nullable', 'string', 'max:255'], 'start_date' => ['sometimes', 'date'], 'end_date' => ['sometimes', 'date', 'after:start_date'], ]); $event->update([...$request->all()]); return new EventResource($event); } /** * Remove the specified resource from storage. */ public function destroy(Event $event) { $event->delete(); return response()->noContent(); } }
api.php
Route::apiResource('events', EventController::class); Route::apiResource('events.attendees', AttendeeController::class) ->scoped()->except(['update']);
原因分析
- 路由参数与控制器参数不匹配:嵌套资源路由
events.attendees生成的路由参数是{event}和{attendee},但你部分控制器方法用了$id、$event_id,导致Laravel无法正确识别要绑定的模型。 scoped()的影响:启用scoped()后,Laravel会自动约束子模型属于父模型,它会尝试用父模型的关联字段(默认是模型名event,而非event_id)去查询子模型,而你的attendees表只有event_id字段,因此抛出“找不到event列”的错误。
解决方法
1. 统一控制器参数与路由参数
将AttendeeController中所有涉及父模型的参数改为Event $event,子模型参数保持Attendee $attendee,修正后的方法如下:
修正后的store方法
public function store(Event $event, Request $request) { $attendee = $event->attendees()->create([ 'user_id' => 1, ]); return new AttendeeResource($attendee); }
修正后的show方法
public function show(Event $event, Attendee $attendee) { return new AttendeeResource($attendee); }
修正后的destroy方法
public function destroy(Event $event, Attendee $attendee) { $attendee->delete(); return response()->noContent(); }
2. 确保数据库字段与关联关系正确
- 确认
attendees表存在event_id字段(外键关联events表的id)。 - 检查
Event模型的关联定义:// app/Models/Event.php public function attendees() { return $this->hasMany(Attendee::class); } - 检查
Attendee模型的关联定义:// app/Models/Attendee.php public function event() { return $this->belongsTo(Event::class); }
3. 理解scoped()的作用
scoped()会自动帮你做权限约束:比如访问/events/1/attendees/2时,Laravel会自动检查attendee的event_id是否等于1,无需手动验证,确保子资源确实属于父资源。
内容的提问来源于stack exchange,提问作者Mahmoud Tokura
相关产品推荐
相关产品推荐

