资源控制器是 Laravel 中用于快速构建 RESTful 风格应用的工具,它将常见的 CRUD 操作(创建、读取、更新、删除)整合到一个控制器中。 配合资源路由,只需一行代码就能生成所有必要的路由,极大提高开发效率。
资源控制器是一个包含 index、create、store、show、edit、update、destroy 七个方法的控制器,
分别对应资源的列表、创建表单、保存、详情、编辑表单、更新、删除操作。通过资源路由,Laravel 会自动将这些方法映射到相应的 URL 和 HTTP 动词。
使用 Artisan 命令 make:controller 并添加 --resource 选项:
php artisan make:controller PostController --resource
生成的控制器位于 app/Http/Controllers/PostController.php,包含了上述七个方法的基本骨架:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index() {}
public function create() {}
public function store(Request $request) {}
public function show($id) {}
public function edit($id) {}
public function update(Request $request, $id) {}
public function destroy($id) {}
}
在 routes/web.php 中,使用 Route::resource 方法注册资源路由:
use App\Http\Controllers\PostController;
Route::resource('posts', PostController::class);
这一行代码会生成以下七个路由:
| HTTP 方法 | URI | 控制器方法 | 路由名称 |
|---|---|---|---|
| GET | /posts | index | posts.index |
| GET | /posts/create | create | posts.create |
| POST | /posts | store | posts.store |
| GET | /posts/{post} | show | posts.show |
| GET | /posts/{post}/edit | edit | posts.edit |
| PUT/PATCH | /posts/{post} | update | posts.update |
| DELETE | /posts/{post} | destroy | posts.destroy |
posts.index、posts.show,方便在代码中使用 route() 辅助函数生成 URL。
如果不需要全部七个动作,可以使用 only 或 except 方法指定保留或排除的动作:
// 只保留 index 和 show
Route::resource('posts', PostController::class)->only(['index', 'show']);
// 排除 create 和 edit
Route::resource('posts', PostController::class)->except(['create', 'edit']);
当资源之间存在父子关系时(如文章下的评论),可以使用嵌套资源路由:
Route::resource('posts.comments', CommentController::class);
这会生成以下路由(以部分为例):
| HTTP 方法 | URI | 控制器方法 | 路由名称 |
|---|---|---|---|
| GET | /posts/{post}/comments | index | posts.comments.index |
| POST | /posts/{post}/comments | store | posts.comments.store |
| GET | /posts/{post}/comments/{comment} | show | posts.comments.show |
| PUT/PATCH | /posts/{post}/comments/{comment} | update | posts.comments.update |
| DELETE | /posts/{post}/comments/{comment} | destroy | posts.comments.destroy |
对应的控制器接收两个参数:父模型和子模型。可以在控制器中利用路由模型绑定简化代码。
如果需要修改默认的路由名称,可以使用 names 方法:
Route::resource('photos', PhotoController::class)->names([
'index' => 'photos.all',
'show' => 'photos.view',
'create' => 'photos.make',
]);
默认路由参数名为资源名称的单数(如 {post}),可以通过 parameters 方法自定义:
Route::resource('users', UserController::class)->parameters([
'users' => 'user_id', // 将 {user} 改为 {user_id}
]);
在控制器方法中,可以直接类型提示模型,Laravel 会自动解析路由参数:
use App\Models\Post;
public function show(Post $post) // {post} 参数自动注入 Post 模型
{
return view('posts.show', compact('post'));
}
public function update(Request $request, Post $post)
{
$post->update($request->all());
return redirect()->route('posts.show', $post);
}
{post} 对应变量 $post。
以下是一个完整的文章资源控制器及路由的使用示例:
路由定义:
Route::resource('posts', PostController::class);
控制器(部分关键方法):
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = Post::latest()->paginate(10);
return view('posts.index', compact('posts'));
}
public function create()
{
return view('posts.create');
}
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|max:255',
'content' => 'required',
]);
Post::create($validated);
return redirect()->route('posts.index')->with('success', '文章创建成功');
}
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
public function edit(Post $post)
{
return view('posts.edit', compact('post'));
}
public function update(Request $request, Post $post)
{
$validated = $request->validate([
'title' => 'required|max:255',
'content' => 'required',
]);
$post->update($validated);
return redirect()->route('posts.show', $post)->with('success', '文章更新成功');
}
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index')->with('success', '文章已删除');
}
}
Route::apiResource('posts', PostController::class):创建无 create 和 edit 路由的 API 资源路由,通常用于纯 API 应用。Route::resource('posts', PostController::class)->shallow():浅层嵌套,在嵌套资源中只保留父 ID 在 URL 中,子资源的独立操作不再需要父 ID。PostsController),与资源路由名一致。authorize 方法或策略进行权限控制。apiResource 避免生成 create 和 edit 路由。names 方法自定义名称,或者使用 name 方法在资源路由基础上添加前缀。另外,可以借助路由分组和命名空间来隔离不同模块。
Route::post('/posts/{post}/publish', [PostController::class, 'publish'])->name('posts.publish');
use 导入。这也是推荐的做法,可以提高代码的 IDE 友好性。
资源控制器和资源路由是 Laravel 实现 RESTful 架构的利器,通过少量代码即可生成标准的 CRUD 路由,减少重复劳动。 掌握资源控制器的使用,能让你快速构建出符合规范的应用,并保持代码的清晰与一致性。 下一章我们将学习表单验证,进一步提升应用的数据安全性。