注解路由

注解路由利用 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 {}

参数详解

参数类型默认值说明
pathsstring[]['']路径列表,支持多路径映射同一处理器
methodstring[]['GET']允许的 HTTP 方法列表
middlewaresstring[][]中间件类名数组
patternsarray<string, string>[]动态参数名 → 正则表达式
domainstring | nullnull限制生效的域名
suffixstring | nullnullURL 后缀要求
titlestring''API 文档中的接口标题
descriptionstring''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());
    }
}

注解优先级

当同一控制器同时使用多种注解时,优先级从高到低为:

  1. #[RouteMapping] 方法级配置(最高优先级)
  2. #[AutoController] / #[Controller] 类级配置

方法级的 #[RouteMapping] 会覆盖类级继承的 prefixmiddlewares 等属性中的同名配置。