Laravel 10 API资源绑定问题:Update与Destroy方法无法正常工作
我正在使用Laravel 10构建REST API,已创建Category模型、控制器及相关资源,路由配置为Route::apiResource('/admin-category', CategoryController::class)。当前index和store功能可正常运行,但update和destroy方法无任何报错却无法生效,且已确认前端请求已正确携带Category ID参数。
相关代码
CategoryController代码
<?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Models\Category; use App\Http\Requests\StoreCategoryRequest; use App\Http\Requests\UpdateCategoryRequest; use App\Http\Resources\CategoryResource; class CategoryController extends Controller { /** * Display a listing of the resource. */ public function index() { return Category::query()->orderBy('id', 'desc') ->paginate(10); } /** * Store a newly created resource in storage. */ public function store(StoreCategoryRequest $request) { $data = $request->validated(); $data['image'] = $request['image']; $data['description'] = $request['description']; Category::create($data); return response(['success' => true, 'msg' => 'New Category created!'], 201); } /** * Display the specified resource. */ public function show(Category $category) { // } /** * Update the specified resource in storage. */ public function update(UpdateCategoryRequest $request, Category $category) { $data = $request->validated(); if(isset($request['image'])){ $data['image'] = $request['image']; } $category->update($data); return response(['success' => true, 'msg' => 'Category updated!'], 200); } /** * Remove the specified resource from storage. */ public function destroy(Category $category) { $category->delete(); return response(['msg' => 'Deleted successfully', 'success' => true], 201); } }
Category模型代码
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Category extends Model { use HasFactory; /** * The attributes that are mass assignable. * * @var array<int, string> */ protected $fillable = [ 'name', 'image', 'description' ]; }
迁移文件代码
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::create('categories', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('image')->nullable(); $table->string('description')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('categories'); } };
原因分析
问题出在隐式模型绑定的参数不匹配:
当使用Route::apiResource('/admin-category', CategoryController::class)时,Laravel生成的路由中,update和destroy方法的参数名是admin-category(来源于路由前缀)。而控制器方法中定义的参数是Category $category,Laravel的隐式模型绑定默认会寻找与参数名(category)一致的路由参数来查询模型,但当前路由参数是admin-category,两者不匹配,导致模型绑定失败——控制器中拿到的是一个空的Category实例,而非对应ID的数据库记录。
对空模型执行update()或delete()不会触发报错,但也不会对数据库中的数据产生任何修改。
解决方法
方法1:指定路由参数与模型绑定的对应关系
修改路由配置,使用parameters()方法将路由参数admin-category映射到模型参数category:
Route::apiResource('/admin-category', CategoryController::class)->parameters([ 'admin-category' => 'category' ]);
方法2:修改控制器参数名匹配路由参数
将控制器中update和destroy方法的参数名改为$adminCategory,与路由参数名一致:
public function update(UpdateCategoryRequest $request, Category $adminCategory) { $data = $request->validated(); if(isset($request['image'])){ $data['image'] = $request['image']; } $adminCategory->update($data); return response(['success' => true, 'msg' => 'Category updated!'], 200); } public function destroy(Category $adminCategory) { $adminCategory->delete(); return response(['msg' => 'Deleted successfully', 'success' => true], 201); }
推荐使用方法1,更符合Laravel的命名规范,也避免后续维护时的混淆。
内容的提问来源于stack exchange,提问作者ziaul haque

