对于习惯使用注解来定义路由的 PHP 开发者来说,Webman 框架在 v2.2.0 版本中加入的注解路由支持无疑是个好消息。这意味着我们终于可以将路由配置直接写在控制器方法上,而无需再频繁地修改独立的 config/route.php 配置文件,让代码的组织和阅读都变得更加直观。
注意:此功能需要 webman-framework >= v2.2.0。
注解路由的基本用法
让我们通过一个示例控制器,快速了解它的基本用法。你需要在控制器类中引入相关的注解类。
namespace app\controller;
use support\annotation\route\DisableDefaultRoute;
use support\annotation\route\Get;
use support\annotation\route\Post;
use support\annotation\route\Route;
#[DisableDefaultRoute]
class UserController
{
#[Get('/user/{id}')]
public function show($id)
{
return "user $id";
}
#[Post('/user')]
public function store()
{
return 'created';
}
#[Route('/user/form', ['GET', 'POST'], 'user.form')]
public function form()
{
return 'form';
}
}
Webman 提供了丰富的 HTTP 方法注解供你使用,包括:#[Get], #[Post], #[Put], #[Delete], #[Patch], #[Head], #[Options] 以及 #[Any](匹配任意 HTTP 方法)。所有路径都必须以 / 开头。部分注解的第二个参数可用于指定路由名称,以便后续使用 route() 辅助函数生成 URL。
控制器类上的 #[DisableDefaultRoute] 注解是可选的。一旦使用,该控制器将禁用 Webman 的默认路由规则(例如 /app/controller/UserController::show 对应的路径),其下的方法只能通过显式定义的注解路由进行访问。
其中,#[Route] 是最通用的注解,其完整用法格式为:#[Route(path, methods, name)]
path:路由路径,以 / 开头。如果设置为 null,则不会注册新路由,仅用于限制默认路由的请求方法(详见下文)。
methods:允许的 HTTP 方法,可以是字符串(如 ‘GET’)或字符串数组(如 [‘GET’, ‘POST’])。
name:路由名称,用于 route(‘name’) 生成 URL,此参数可以省略。
无路径注解:仅限制默认路由的请求方法
如果你不指定路径参数,那么注解将仅用于限制该控制器方法可以通过哪些 HTTP 方法访问,而其 URL 路径仍然遵循 Webman 的默认路由规则。
#[Post]
public function create()
{
... // 此方法仅允许 POST 请求访问,路径仍为 /user/create
}
#[Get]
public function index()
{
... // 此方法仅允许 GET 请求访问
}
你还可以组合多个无路径注解,来允许多种请求方法:
#[Get]
#[Post]
public function form()
{
... // 允许 GET 和 POST 两种请求方法访问默认路由
}
对于没有在注解中声明的 HTTP 请求方法,框架将返回 405 Method Not Allowed 响应。
需要注意的是,如果一个方法上使用了多个带路径的注解,它们将会被注册为多条独立的路由。例如 #[Get(‘/a’)] #[Post(‘/b’)] 会产生 GET /a 和 POST /b 两条路由。
使用路由组前缀
如果你想为一组路由添加统一的前缀,可以在控制器类上使用 #[RouteGroup] 注解。
use support\annotation\route\RouteGroup;
use support\annotation\route\Get;
#[RouteGroup('/api/v1')]
class UserController
{
#[Get('/user/{id}')] // 此方法实际的访问路径将是 /api/v1/user/{id}
public function show($id)
{
...
}
}
自定义请求方法与路由名
如前所述,#[Route] 注解可以灵活地定义自定义的 HTTP 方法组合和路由名。
use support\annotation\route\Route;
#[Route('/user', ['GET', 'POST'], 'user.form')]
public function form()
{
... // 允许 GET 和 POST 方法,路由名为 ‘user.form’
}
// 也可以只指定路径和方法,不设置路由名
#[Route('/user/update', 'PUT')]
public function update()
{
... // 仅允许 PUT 方法,无路由名
}
路径参数与正则约束
注解路由的路径定义完全支持与 config/route.php 中相同的参数语法,包括正则表达式约束和可选参数。
#[Get('/user/{id:\d+}')] // 仅匹配数字类型的 id 参数
public function show($id)
{
...
}
#[Get('/user[/{name}]')] // name 为可选参数,匹配 /user 或 /user/xxx
public function list($name = null)
{
...
}
#[Any('/user/[{path:.+}]')] // 匹配 /user 及 /user/ 开头的任意后续路径
public function catchAll($path = null)
{
...
}
关于路由参数更详细的语法规则,可以查阅 Webman 官方文档中的「路由参数」章节。
中间件的使用
你可以通过 #[Middleware] 注解为控制器或方法添加中间件,其用法与 support\annotation\Middleware 一致,并且会作用于通过注解定义的路由。
use support\annotation\Middleware;
// 为整个控制器添加中间件
#[Middleware(\app\middleware\AuthMiddleware::class)]
class UserController
{
...
}
// 为单个方法添加中间件
#[Get('/user/{id}')]
#[Middleware(\app\middleware\RateLimitMiddleware::class)]
public function show($id)
{
...
}
与 route() URL 生成函数的配合
如果你在注解中指定了路由名(name),那么就可以方便地使用 route(‘name‘, $params) 来生成对应的 URL,这在模板或业务逻辑中非常实用。
#[Get('/user/{id}', 'user.show')]
public function show($id)
{
...
}
// 使用示例:route(‘user.show’, [‘id’ => 123]) 将会生成 /user/123
Webman 此次对注解路由的支持,极大地提升了PHP框架在定义路由时的开发体验和代码内聚性,让项目结构更加清晰。如果你对 Webman 的其他特性或高级用法感兴趣,欢迎到云栈社区的相应板块与更多开发者交流探讨。