注解路由
注解路由利用 PHP 8 的 Attributes(注解)特性,在控制器类和方法上直接声明路由规则。相比配置文件方式,注解路由使路由定义与业务代码紧密关联,更利于维护和阅读。
三种注解类型
| 注解 | 作用域 | 说明 |
|---|---|---|
#[Controller] | 类级别 | 声明控制器分组前缀和共享中间件 |
#[AutoController] | 类级别 | 自动将该类所有 public 方法注册为路由 |
#[RouteMapping] | 方法级别 | 精确控制单个方法的路由规则 |
Controller 注解
#[Controller] 为控制器设置分组级别的公共属性,类中各方法继承这些配置。
基本用法
php
use Viswoole\Router\Annotation\Controller;
#[Controller(prefix: '/api/v1')]
class UserController
{
public function info(): array
{
// 路由: GET /api/v1/info
// 方法名直接作为路径后段
return ['name' => 'Viswoole'];
}
public function userList(): array
{
// 路由: GET /api/v1/user_list
return [];
}
}配置中间件
php
#[Controller(
prefix: '/api/v1',
middlewares: [AuthMiddleware::class, RateLimitMiddleware::class],
)]
class ApiController
{
// 所有方法自动继承上述中间件
}配置域名
php
#[Controller(prefix: '/api', domain: 'api.example.com')]
class ApiV1Controller
{
// 仅在 api.example.com 域名下生效
}AutoController 注解
#[AutoController] 自动扫描控制器的所有 public 方法并生成路由,无需逐个标注。
基本用法
php
use Viswoole\Router\Annotation\AutoController;
#[AutoController(prefix: '/admin')]
class AdminController
{
public function dashboard(): string
{
// 路由: GET /admin/dashboard
return 'Dashboard';
}
public function settings(): array
{
// 路由: GET /admin/settings
return [];
}
}注意:AutoController 设置
prefix后,方法路径为prefix/methodname,不会重复添加类名段。如需自定义路径,请使用#[RouteMapping]。
RouteMapping 注解
#[RouteMapping] 提供最精细的路由控制,可在方法级别覆盖类的分组配置。
完整参数说明
php
#[RouteMapping(
paths: ['/user/info', '/user/profile'], // 支持多路径映射到同一方法
method: ['GET', 'POST'], // 允许的 HTTP 方法
middlewares: [AuthMiddleware::class], // 方法级中间件
patterns: ['id' => '\d+'], // 动态参数正则约束
domain: 'api.example.com', // 域名限制
suffix: '', // 后缀要求(空字符串表示无后缀)
title: '用户信息', // API 文档标题
description: '获取用户基本信息', // API 文档描述
)]
public function info(int $id): array {}参数详解
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
paths | string[] | [''] | 路径列表,支持多路径映射同一处理器 |
method | string[] | ['GET'] | 允许的 HTTP 方法列表 |
middlewares | string[] | [] | 中间件类名数组 |
patterns | array<string, string> | [] | 动态参数名 → 正则表达式 |
domain | string | null | null | 限制生效的域名 |
suffix | string | null | null | URL 后缀要求 |
title | string | '' | API 文档中的接口标题 |
description | string | '' | API 文档中的接口描述 |
单一路径
php
#[RouteMapping(paths: ['/profile'], method: ['GET'], title: '个人资料')]
public function profile(): array
{
return ['id' => 1, 'name' => 'Test'];
}多路径映射
php
#[RouteMapping(
paths: ['/me', '/my/profile', '/user/profile'],
method: ['GET'],
title: '当前用户信息',
)]
public function me(): array
{
return ['user' => '当前用户'];
}动态参数
php
#[RouteMapping(
paths: ['/article/{category}/{id}'],
method: ['GET'],
patterns: [
'category' => '[a-zA-Z]+',
'id' => '\d+',
],
title: '文章详情',
)]
public function article(string $category, int $id): array
{
return compact('category', 'id');
}
// 请求: GET /article/php/42
// 结果: $category = 'php', $id = 42可选参数
php
#[RouteMapping(paths: ['/search/{keyword?}'], method: ['GET'])]
public function search(string $keyword = ''): array
{
// /search → $keyword = ''
// /search/viswoole → $keyword = 'viswoole'
return ['keyword' => $keyword];
}混合使用示例
以下展示 #[Controller] 与 #[RouteMapping] 组合的实际应用场景:
php
<?php
namespace App\Controller\Api\V1;
use App\Middleware\AuthMiddleware;
use Viswoole\Router\Annotation\Controller;
use Viswoole\Router\Annotation\RouteMapping;
#[Controller(
prefix: '/api/v1',
middlewares: [AuthMiddleware::class],
)]
class OrderController
{
#[RouteMapping(
paths: ['/order/list'],
method: ['GET'],
title: '订单列表',
description: '分页获取当前用户的订单记录',
)]
public function list(int $page = 1, int $pageSize = 20): array
{
return OrderService::paginate($page, $pageSize);
}
#[RouteMapping(
paths: ['/order/{id}'],
method: ['GET'],
patterns: ['id' => '\d+'],
title: '订单详情',
)]
public function detail(int $id): array
{
return OrderService::find($id);
}
#[RouteMapping(
paths: ['/order/create'],
method: ['POST'],
title: '创建订单',
middlewares: [ValidateOrderMiddleware::class], // 额外追加中间件
)]
public function create(Request $request): array
{
return OrderService::create($request->all());
}
}注解优先级
当同一控制器同时使用多种注解时,优先级从高到低为:
#[RouteMapping]方法级配置(最高优先级)#[AutoController]/#[Controller]类级配置
方法级的 #[RouteMapping] 会覆盖类级继承的 prefix、middlewares 等属性中的同名配置。
