路由系统
最后更新: 2026-01-27 11:02:47路由系统
Unicode Framework 提供了强大且灵活的路由系统,支持 RESTful 路由、路由组、中间件、命名路由等功能。
基础路由
基本语法
路由定义在 route.php 文件中(框架级别)或 app/{app-name}/route.php 文件中(应用级别)。
use Unicode\Framework\Route\Route;
// GET 路由
Route::get('/users', [UserController::class, 'index']);
// POST 路由
Route::post('/users', [UserController::class, 'store']);
// PUT 路由
Route::put('/users/{id}', [UserController::class, 'update']);
// PATCH 路由
Route::patch('/users/{id}', [UserController::class, 'updatePartial']);
// DELETE 路由
Route::delete('/users/{id}', [UserController::class, 'destroy']);
路由处理器
路由处理器可以是:
- 闭包函数
Route::get('/hello', function() {
return ['message' => 'Hello, World!'];
});
Route::get('/users', [UserController::class, 'index']);
Route::get('/users/{id}', function(Request $request, int $id) {
return ['user_id' => $id];
});
HTTP 方法
框架支持所有标准 HTTP 方法:
Route::get('/resource', $handler);
Route::post('/resource', $handler);
Route::put('/resource/{id}', $handler);
Route::patch('/resource/{id}', $handler);
Route::delete('/resource/{id}', $handler);
Route::options('/resource', $handler);
Route::head('/resource', $handler);
路由参数
必需参数
使用 {param} 语法定义路由参数:
Route::get('/users/{id}', [UserController::class, 'show']);
// 访问 /users/123,$id = 123
可选参数
使用 {param?} 语法定义可选参数:
Route::get('/posts/{id?}', [PostController::class, 'show']);
// 访问 /posts,$id = null
// 访问 /posts/123,$id = 123
参数约束
路由参数会自动进行类型转换。在控制器方法中,可以指定参数类型:
// 路由定义
Route::get('/users/{id}', [UserController::class, 'show']);
// 控制器方法
public function show(Request $request, int $id): array
{
// $id 自动转换为整数
return ['user_id' => $id];
}
多个参数
Route::get('/users/{userId}/posts/{postId}', function(Request $request, int $userId, int $postId) {
return [
'user_id' => $userId,
'post_id' => $postId,
];
});
路由组
路由组允许您为一组路由共享公共属性(前缀、中间件等)。
前缀组
Route::group('/api/v1', function() {
Route::get('/users', [UserController::class, 'index']);
Route::post('/users', [UserController::class, 'store']);
Route::get('/users/{id}', [UserController::class, 'show']);
});
// 实际路由:
// GET /api/v1/users
// POST /api/v1/users
// GET /api/v1/users/{id}
嵌套路由组
Route::group('/api', function() {
Route::group('/v1', function() {
Route::get('/users', [UserController::class, 'index']);
});
});
// 实际路由:GET /api/v1/users
中间件
单个路由中间件
use Unicode\Framework\Auth\Middleware\JwtMiddleware;
Route::get('/profile', [UserController::class, 'profile'], 'profile', [
JwtMiddleware::class
]);
中间件组
Route::middleware([JwtMiddleware::class], function() {
Route::get('/profile', [UserController::class, 'profile']);
Route::put('/profile', [UserController::class, 'updateProfile']);
});
嵌套中间件组
Route::middleware([AuthMiddleware::class], function() {
Route::middleware([AdminMiddleware::class], function() {
Route::get('/admin/users', [AdminController::class, 'users']);
});
});
组合使用(前缀 + 中间件)
Route::group('/api/v1', function() {
Route::middleware([JwtMiddleware::class], function() {
Route::get('/users', [UserController::class, 'index']);
Route::post('/users', [UserController::class, 'store']);
});
});
命名路由
命名路由允许您通过名称生成 URL,而不需要硬编码路径。
定义命名路由
Route::get('/users/{id}', [UserController::class, 'show'], 'users.show');
生成 URL
use function router;
// 生成 URL
$url = router()->url('users.show', ['id' => 123]);
// 结果:/users/123
// 生成完整 URL(包含域名)
$fullUrl = router()->url('users.show', ['id' => 123], true);
在控制器中使用
class UserController
{
public function index(Request $request): array
{
$url = router()->url('users.show', ['id' => 1]);
return ['show_url' => $url];
}
}
检查路由是否存在
if (router()->hasRoute('users.show')) {
$url = router()->url('users.show', ['id' => 1]);
}
路由缓存
在生产环境中,框架会自动缓存路由以提高性能。
启用路由缓存
路由缓存在生产环境(APP_ENV=production)下自动启用。
缓存位置
路由缓存文件位于:bootstrap/cache/routes.php
清除路由缓存
删除 bootstrap/cache/routes.php 文件即可清除缓存。框架会在下次请求时重新生成缓存。
开发环境
在开发环境(APP_ENV=development)下,路由不会使用缓存,每次修改路由文件后立即生效。
最佳实践
1. RESTful 路由组织
// 推荐:使用路由组组织 RESTful API
Route::group('/api/v1', function() {
// 用户资源
Route::get('/users', [UserController::class, 'index'], 'api.users.index');
Route::post('/users', [UserController::class, 'store'], 'api.users.store');
Route::get('/users/{id}', [UserController::class, 'show'], 'api.users.show');
Route::put('/users/{id}', [UserController::class, 'update'], 'api.users.update');
Route::delete('/users/{id}', [UserController::class, 'destroy'], 'api.users.destroy');
// 文章资源
Route::get('/posts', [PostController::class, 'index'], 'api.posts.index');
Route::post('/posts', [PostController::class, 'store'], 'api.posts.store');
// ...
});
2. 中间件分层
// 公共中间件(所有 API 路由)
Route::group('/api', function() {
Route::middleware([CorsMiddleware::class], function() {
// 需要认证的路由
Route::middleware([JwtMiddleware::class], function() {
Route::get('/profile', [UserController::class, 'profile']);
});
// 公开路由
Route::get('/posts', [PostController::class, 'index']);
});
});
3. 路由命名规范
使用点号分隔的命名空间风格:
Route::get('/api/v1/users', [UserController::class, 'index'], 'api.v1.users.index');
Route::get('/api/v1/users/{id}', [UserController::class, 'show'], 'api.v1.users.show');
Route::get('/admin/users', [AdminController::class, 'index'], 'admin.users.index');
4. 控制器组织
// 推荐:按功能模块组织路由
Route::group('/api/v1', function() {
// 用户相关
Route::group('/users', function() {
Route::get('/', [UserController::class, 'index']);
Route::post('/', [UserController::class, 'store']);
Route::get('/{id}', [UserController::class, 'show']);
});
// 文章相关
Route::group('/posts', function() {
Route::get('/', [PostController::class, 'index']);
Route::post('/', [PostController::class, 'store']);
});
});
5. 路由文件组织
对于大型项目,可以将路由拆分到多个文件:
// app/index/route.php
require __DIR__ . '/routes/api.php';
require __DIR__ . '/routes/web.php';
require __DIR__ . '/routes/admin.php';
常见问题
Q: 路由冲突怎么办?
A: 框架支持路由覆盖。如果定义了两个相同方法和路径的路由,后定义的路由会覆盖先定义的路由。
Q: 如何获取当前路由信息?
A: 在控制器中通过 Request 对象获取:
public function index(Request $request): array
{
$routeName = $request->getAttribute('routeName');
$routePath = $request->getAttribute('routePath');
$params = $request->getAttribute('routeParams');
return [
'name' => $routeName,
'path' => $routePath,
'params' => $params,
];
}
Q: 如何限制路由参数格式?
A: 在控制器方法中使用类型提示,框架会自动进行类型转换和验证:
Route::get('/users/{id}', [UserController::class, 'show']);
public function show(Request $request, int $id): array
{
// $id 必须是整数,否则会返回 404
}
Q: 路由顺序重要吗?
A: 是的。路由按照定义的顺序进行匹配,第一个匹配的路由会被使用。建议将更具体的路由放在前面。
// 正确:具体路由在前
Route::get('/users/new', [UserController::class, 'create']);
Route::get('/users/{id}', [UserController::class, 'show']);
// 错误:如果顺序相反,/users/new 会被匹配为 /users/{id},id = 'new'