第 2.5 章:API 路由
学习时间: 45 分钟
1. 什么是路由?通俗易懂的解释
想象一下,您的控制器 (PlanetController
) 是一个大型办公中心,它的每个方法 (index
, store
, show
) 都是一个执行自身工作的部门。
路由 (Route) 是建筑物入口处的地址牌。它指明:
- “如果有人使用 GET 方法访问
/planets
地址——将其发送到index
部门(显示所有)。” - “如果有人使用 POST 方法访问
/planets
地址并携带数据——将其发送到store
部门(创建新记录)。”
没有路由,外部世界的任何请求都无法在您的代码中找到它所需的部门。API 中此类“地址牌”的主要文件是 routes/api.php
。
在 Laravel 11+ 中,默认没有“API 地址簿”。我们通过执行 php artisan install:api
命令自行创建了它。现在我们有了 routes/api.php
文件——它是我们 API 所有路由的主要管理中心。
api.php
与 web.php
的主要区别:
/api
前缀:Laravel 会自动为此文件中的所有 URL 地址添加/api
前缀。/planets
路由会变为/api/planets
。- “无状态” (Stateless):这里没有像普通 Web 应用那样的会话和 Cookie 文件。每个请求都是独立的,并且必须包含所有身份验证信息(通常是请求头中的 API 令牌)。
2. 新手之路:手动创建路由
让我们手动创建一个路由,以便理解其原理。我们的目标是让 URL /api/planets
显示所有行星的列表。
打开 routes/api.php
并写入:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PlanetController; // 指明控制器位置
// (1) (2) (3)
Route::get( '/planets', [PlanetController::class, 'index'] );
// ^ ^ ^
// (HTTP 方法) (URL 地址) (要调用哪个控制器和方法)
逐行分析这段代码:
Route::get(...)
— 我们说:“这个路由仅适用于 GET 请求。”'/planets'
— 这是 Laravel 将监听的 URL。考虑到/api
前缀,完整地址将是http://space-api.test/api/planets
。[PlanetController::class, 'index']
— 这是“目的地”。我们说:“当请求到来时,找到PlanetController
类并调用其中的index()
方法。”
现在一切都关联起来了! 请求 -> 路由 -> 控制器 -> 方法。
那么,如果我们需要通过行星 ID 获取一个行星呢?例如,/api/planets/5
。
这里 {planet}
是一个“模板”或变量。Laravel 明白这个位置可以是任何内容(ID、slug)。然后它将此值传递给 show(Planet $planet)
方法。Laravel 自动通过 ID 查找行星的这种“魔力”称为 路由模型绑定 (Route Model Binding)。
3. 大师之路:apiResource
—— 一行代码统治一切
手动为每个路由(index
, show
, store
, update
, destroy
)创建很繁琐。Laravel 开发者明白这一点,因此创建了一个强大的助手——apiResource
。
删除我们所写的所有内容,并用一行代码替换:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PlanetController;
Route::apiResource('planets', PlanetController::class);
这一行代码在底层做了什么? 它会自动为我们在控制器中已经实现的标准 CRUD 操作创建一整套路由。
方法 | URL | 映射到方法 | 用途 |
---|---|---|---|
GET | /api/planets |
index() |
获取所有行星列表 |
POST | /api/planets |
store() |
创建一个新行星 |
GET | /api/planets/{planet} |
show() |
显示一个特定的行星 |
PUT/PATCH | /api/planets/{planet} |
update() |
更新现有行星 |
DELETE | /api/planets/{planet} |
destroy() |
删除行星 |
您可以亲自验证。在终端中执行命令:
您将看到一个包含所有已创建路由的表格。apiResource
是您在创建标准 API 时节省时间的最佳伙伴。
4. 特殊任务和路由顺序
如果我们需要一个 apiResource
中没有的非标准路由怎么办?例如,通过地址 /api/planets/random
获取一个随机行星。
让我们添加它。但这里有一个致命陷阱,十有八九的新手都会掉进去。
错误的顺序 (不工作!):
Route::apiResource('planets', PlanetController::class);
Route::get('/planets/random', [PlanetController::class, 'random']); // <-- 不工作
Route::apiResource
,它创建了 GET /planets/{planet}
路由。当您请求 /planets/random
时,Laravel 会认为 "random" 是行星的 ID,并尝试在数据库中查找 ID 为 "random" 的行星,您将收到错误。
正确的顺序 (工作!):
<?php
use App\Http\Controllers\PlanetController;
use Illuminate\Support\Facades\Route;
// 1. 首先声明具体路由
Route::get('/planets/random', [PlanetController::class, 'random']);
// 2. 然后才声明带变量的通用路由
Route::apiResource('planets', PlanetController::class);
⚠️ 重要提示!
为了测试 api/planets/random 路由,需要在 PlanetController 中添加一个新的处理程序:
规则: 始终在更通用和模板化的路由(例如 /{planet}
)之前声明更具体的路由(例如 /random
)。
5. 路由分组:整理顺序
当路由数量增多时,可以并且应该对它们进行分组。
A. API 版本控制
为了将来不破坏使用您的 API 的旧应用程序,通常会在 URL 中添加版本,例如 /api/v1/...
。
<?php
Route::prefix('v1')->group(function () {
// 此组内的所有路由都将获得 /v1 前缀
// 最终 URL: /api/v1/planets
Route::get('/planets/random', [PlanetController::class, 'random']);
Route::apiResource('planets', PlanetController::class);
});
B. 路由保护 (中间件) 假设所有人都可以查看行星,但只有授权用户才能创建、更新和删除行星。
<?php
// 对所有人公开的路由
Route::get('/planets', [PlanetController::class, 'index']);
Route::get('/planets/{planet}', [PlanetController::class, 'show']);
// 需要“通行证”(身份验证)的路由组
Route::middleware('auth:sanctum')->group(function () {
Route::post('/planets', [PlanetController::class, 'store']);
Route::put('/planets/{planet}', [PlanetController::class, 'update']);
Route::delete('/planets/{planet}', [PlanetController::class, 'destroy']);
});
这里 middleware('auth:sanctum')
就像一个保安,检查每个试图访问组内路由的人的“通行证”。
6. 通过 Postman 进行测试
现在所有路由都已设置好,是时候进行测试了。
- 如果您使用 Herd: 您的网站已在
http://space-api.test
之类的地址上运行。 - 如果没有: 通过命令
php artisan serve
启动本地服务器。地址将是http://localhost:8000
。
打开 Postman 并发送请求:
GET http://space-api.test/api/planets
GET http://space-api.test/api/planets/random
POST http://space-api.test/api/planets
(不要忘记在Body
->raw
->JSON
选项卡中添加 JSON 请求体)。
POST 请求示例:
{
"name": "Kepler-186f",
"description": "宜居带中第一个地球大小的行星",
"size_km": 15000,
"solar_system": "Kepler-186",
"is_habitable": true
}
8. 常见的路由错误
- 404 Not Found
- URL 不正确 (
/api/planet
而不是/api/planets
) - 忘记运行
php artisan serve
- URL 不正确 (
- 405 Method Not Allowed
- HTTP 方法不正确(例如,GET 而不是 POST)
- Missing Controller
- 控制器名称拼写错误 (
PlanetControler
)
- 控制器名称拼写错误 (
- Route Name Collision
- 路由名称冲突
巩固知识的小测验
🚀 本章总结:
您已经为宇宙 API 构建了“超空间路由”!现在:
- 🗺️ 所有端点均可通过
/api/...
访问 - 🔗 资源路由已连接到控制器
- 🛡️ 已添加自定义路由以进行特殊操作
- ✅ 路由已通过 Postman 测试
宇宙已开放请求! 接下来,我们将添加针对“太空垃圾”的防护 — 数据验证。
📌 检查:
- 执行
php artisan route:list
- 确认您能看到 5+ 个 planets 路由
- 在浏览器/Postman 中测试 GET /api/planets 的工作情况
⚠️ 如果出现 404 错误:
- 检查
routes/api.php
中是否存在Route::apiResource
- 确保服务器已启动 (
php artisan serve
)- 对于 Windows:在防火墙中允许端口 8000