Hyperf框架作为基于Swoole的高性能PHP协程框架,其路由系统是整个Web应用的入口,负责将客户端请求分发到对应的处理逻辑,Hyperf的路由组件基于PSR-7标准设计,支持灵活的路由定义、参数约束、中间件机制等功能,能够满足复杂业务场景的需求,本文将详细介绍Hyperf路由的核心功能及使用方法,帮助开发者快速掌握路由配置技巧。

路由的基本定义
Hyperf的路由定义通过HyperfHttpServerRouterRouter类提供的方法实现,支持常见的HTTP请求方法,如GET、POST、PUT、DELETE等,基本语法为在路由配置文件(通常为config/routes.php或config/routes/*.php)中调用Router的对应方法,并指定路由路径和处理器。
闭包处理器
闭包是最简单的处理器形式,适合快速实现接口或简单逻辑:
use HyperfHttpServerRouterRouter;
Router::get('/', function () {
return 'Hello, Hyperf!';
});
Router::post('/api/login', function (PsrHttpMessageServerRequestInterface $request) {
$data = $request->getParsedBody();
return ['token' => 'sample-token'];
});
闭包中可以直接注入PsrHttpMessageServerRequestInterface请求对象,用于获取请求参数、头部等信息。
控制器处理器
实际开发中更常用的是控制器处理器,将业务逻辑封装到类方法中:
use HyperfHttpServerRouterRouter;
Router::get('/user/{id}', [AppControllerUserController::class, 'show']);
控制器需继承HyperfHttpServerAnnotationController注解,并定义对应方法,例如UserController中的show方法:
#[Controller]
class UserController
{
#[GetMapping(path: '/user/{id}')]
public function show(int $id)
{
return ['id' => $id, 'name' => 'John'];
}
}
通过注解#[GetMapping]可以明确路由方法和路径,支持IDE类型提示和路由扫描。
路由参数与约束
路由参数允许从URL中提取动态数据,Hyperf支持必选参数、可选参数及参数约束。
必选参数
用包裹参数名,如/user/{id},参数会自动注入到处理器方法中:
Router::get('/user/{id}', function ($id) {
return "User ID: {$id}";
});
可选参数
参数后添加标记为可选,需提供默认值:
Router::get('/user/{name?}', function ($name = 'Guest') {
return "Hello, {$name}";
});
参数约束
通过正则表达式约束参数格式,避免无效参数进入业务逻辑:
Router::get('/user/{name:[a-zA-Z]+}', function ($name) {
return "User: {$name}";
});
参数约束规则需紧跟参数名,用分隔,例如d+匹配数字,[a-z]+匹配小写字母等,以下是常见参数约束示例:
| 参数约束 | 说明 | 示例路径 |
|---|---|---|
{id:d+} |
匹配1个或多个数字 | /user/123 |
{name:w+} |
匹配字母、数字、下划线 | /user/john_doe |
{year:d{4}} |
匹配4位数字 | /blog/2023 |
{slug:[a-z-]+} |
匹配小写字母和连字符 | /post/hello-world |
路由分组与中间件
路由分组可以将具有共同特征的路由(如相同前缀、中间件)归为一组,减少重复代码,提升可维护性。
路由前缀分组
通过Router::group()的prefix参数统一设置路径前缀:
Router::group(function () {
Router::get('/profile', function () { return 'Profile Page'; });
Router::get('/settings', function () { return 'Settings Page'; });
}, ['prefix' => '/user']);
上述代码会生成/user/profile和/user/settings两条路由。

中间件分组
中间件用于请求前后的处理逻辑(如身份验证、日志记录),分组可统一应用中间件:
Router::group(function () {
Router::get('/dashboard', function () { return 'Dashboard'; });
Router::post('/data', function () { return 'Data Saved'; });
}, ['middleware' => [AppMiddlewareAuthMiddleware::class]]);
中间件类需实现HyferrMiddlewareInterface接口,或使用注解#[Middleware]定义,中间件执行顺序与定义顺序一致,全局中间件可在config/autoload/middlewares.php中配置。
域分组
通过domain参数实现多域名路由分组,适用于多租户或子域名场景:
Router::group(function () {
Router::get('/info', function () { return 'Admin Info'; });
}, ['domain' => 'admin.example.com', 'prefix' => '/api']);
需确保服务器配置支持泛域名解析(如*.example.com)。
路由命名与URL生成
为路由命名后,可通过route()函数动态生成URL,避免硬编码路径。
路由命名
使用name()方法为路由指定唯一名称:
Router::get('/user/profile', [UserController::class, 'profile'])->name('profile');
Router::post('/user/avatar', [UserController::class, 'avatar'])->name('avatar.upload');
URL生成
在控制器或闭包中调用route()函数生成URL:
use HyperfDiAnnotationInject;
use HyperfHttpServerContractUrlGeneratorInterface;
#[Controller]
class UserController
{
#[Inject]
private UrlGeneratorInterface $urlGenerator;
public function redirect()
{
$url = $this->urlGenerator->route('profile');
return $this->response->withStatus(302)->withHeader('Location', $url);
}
}
route()函数支持参数传递,自动替换URL中的占位符:
$url = $this->urlGenerator->route('user.show', ['id' => 123]); // /user/123
路由模型绑定
路由模型绑定可将路由参数直接与Eloquent模型关联,减少手动查询逻辑。
隐式绑定
默认情况下,Hyperf会根据参数名(如id)查找对应模型(如User模型):
Router::get('/user/{user}', [UserController::class, 'show']);
#[Controller]
class UserController
{
public function show(User $user) // 自动注入User模型实例
{
return $user->toArray();
}
}
需确保模型的主键字段与参数名一致(默认为id)。
显式绑定
通过Router::model()方法自定义参数与模型的映射关系:
Router::model('post', AppModelPost::class);
Router::get('/post/{post}', [PostController::class, 'show']);
这样{post}参数会自动绑定到Post模型实例,若模型不存在会抛出ModelNotFoundException异常。
RESTful资源路由
Hyperf提供resource()方法快速生成符合RESTful规范的路由,适用于资源型接口(如用户、文章等)。

定义资源路由
Router::resource('posts', PostController::class);
上述代码会自动生成7条标准路由,如下表所示:
| 方法 | 路径 | 控制器方法 | 作用 |
|---|---|---|---|
| GET | /posts | index | 列表资源 |
| POST | /posts | store | 创建资源 |
| GET | /posts/{id} | show | 显示单个资源 |
| PUT | /posts/{id} | update | 更新资源 |
| PATCH | /posts/{id} | update | 部分更新资源 |
| DELETE | /posts/{id} | destroy | 删除资源 |
自定义资源路由
若需调整生成的路由(如添加自定义方法),可通过except或only参数:
Router::resource('posts', PostController::class)->only(['index', 'show', 'store']);
Router::resource('comments', CommentController::class)->except(['create', 'edit']);
路由缓存
生产环境中,路由缓存可显著提升路由匹配效率,通过以下命令生成缓存:
php bin/hyperf.php route:cache
缓存文件位于runtime/route.php,清除缓存使用:
php bin/hyperf.php route:clear
注意:修改路由后需重新生成缓存,否则路由变更不会生效。
路由异常处理
404未找到路由
默认情况下,未匹配的路由会返回404错误,可通过fallback路由自定义处理:
Router::fallback(function () {
return ['code' => 404, 'message' => 'Page Not Found'];
});
405方法不允许
若请求方法与路由定义不匹配(如GET请求POST路由),返回405错误,可通过HttpMethodNotAllowedHandler自定义处理逻辑,或在config/autoload/exceptions.php中配置异常处理器。
相关问答FAQs
问题1:Hyperf中如何为路由参数添加自定义正则约束,并在参数不符合约束时返回自定义错误信息?
答:通过路由参数的正则约束功能可实现参数格式校验,限制id必须为4位数字:
Router::get('/test/{id:d{4}}', function ($id) {
return "ID: {$id}";
});
若参数不符合正则规则(如/test/123),Hyperf会自动返回404错误,若需自定义错误信息,可结合全局异常处理,在config/autoload/exceptions.php中定义NotFoundHttpException的处理器:
'exceptions' => [
HyperfHttpMessageExceptionNotFoundHttpException::class => [
AppExceptionHandlerRouterExceptionHandler::class,
],
],
然后在RouterExceptionHandler中捕获异常并返回自定义响应:
public function handle(Throwable $throwable, RequestInterface $request)
{
if ($throwable instanceof NotFoundHttpException) {
return ['code' => 400, 'message' => 'Parameter format error'];
}
return parent::handle($throwable, $request);
}
问题2:如何在Hyperf中实现路由组的条件中间件(例如仅对特定用户角色应用中间件)?
答:可通过闭包中间件结合路由分组参数实现条件中间件,仅对admin角色用户应用权限中间件:
Router::group(function ($router) {
$router->get('/admin/dashboard', function () { return 'Admin Dashboard'; });
$router->get('/admin/users', function () { return 'User List'; });
}, [
'prefix' => '/admin',
'middleware' => function (PsrHttpMessageServerRequestInterface $request, $next) {
$user = $request->getAttribute('user'); // 假设已通过中间件注入用户信息
if ($user && $user->role === 'admin') {
return $next($request);
}
return ['code' => 403, 'message' => 'Forbidden'];
},
]);
上述代码中,闭包中间件会检查用户角色,仅允许admin用户访问分组内路由,也可将角色判断逻辑抽离为独立中间件类,通过依赖注入实现更灵活的控制。
来源互联网整合,作者:小编,如若转载,请注明出处:https://www.aiboce.com/ask/267833.html