hyperf路径参数校验必须在路由定义中用正则约束(如{id:\d+}),@validate注解不处理路径参数;取值须用类型提示、@param注解或$request->route()->parameters(),不可用$input();注解路由生效需启用scan、添加@controller/@autocontroller并清缓存。

Hyperf 路由参数传递不是“传参”而是“提取+校验”,关键在路径定义、注解写法和取值方式三者配合。写错位置(比如把正则放在验证器里)或取值方法不对(比如用 $request->input() 拿路径参数),都会导致参数丢失或校验失效。
路径参数必须在路由定义时加正则约束
Hyperf 的路径参数(如 /user/{id} 中的 id)**不会被 @Validate 注解处理**,它只管 query、body 和 form。想让 {id} 必须是数字,就得在路由路径里直接写正则:
-
#[GetMapping("/user/{id:\d+}")]——\d+表示至少一位数字 -
Router::get("/order/{sn:[0-9a-f]{32}}", [...])—— 匹配 32 位小写十六进制订单号 -
/api/v1/posts/{year:\d{4}}/{month:\d{2}}—— 多段带格式的参数都得显式声明 - 不写正则(如
/user/{id})= 任意字符串都能匹配进来,后续全靠手动判断
控制器里正确获取路径参数
路径参数不能用 $request->input('id') 或 $request->query('id'),它们只读查询参数和表单数据。必须用以下任一方式:
- 类型提示自动注入:
public function show(int $id)(框架自动转换并校验类型) - 参数注解注入:
public function show(#[Param('id')] int $id) - 手动从路由对象取:
$id = $request->route()->parameters()['id'] ?? null
注意:如果用了 @Validate 校验 id,它只对 query/body 生效,对路径参数无效 —— 所以别指望它拦住 /user/abc 这种请求。
可选路径段和复杂校验的写法
需要支持可选参数(比如 /user/123 或 /user/123/profile),用 FastRoute 的方括号语法:
-
#[GetMapping("/user/{id:\d+}[/{tab:[a-z]+}]")]——[...]内为可选段,tab不传时值为null - 若需查库校验(如 “用户是否存在”)或规则超出正则能力(如 “id 必须是偶数”),放弃纯路由层拦截,在控制器里手动验证:
示例:
$validator = $this->validatorFactory->make(
['id' => $id],
['id' => 'required|exists:users,id'],
['id.exists' => '用户不存在']
);
if ($validator->fails()) {
throw new ValidationException($validator);
}
注解路由生效的前提条件
写了 #[GetMapping] 却没注册成功?大概率卡在这三步:
- 确认
config/autoload/annotations.php中'scan' => true已开启,且'paths'包含控制器目录(如app/Controller) - 控制器类顶部必须有
#[Controller]或#[AutoController],否则框架不扫描其方法 - 改完配置后清空
runtime/container和runtime/cache目录,避免缓存干扰
验证是否注册成功,最直接的方法是运行 php bin/hyperf.php route:list,看输出里有没有你的路径和 HTTP 方法。











