Wave Router需手动为每个HTTP方法调用add注册RESTful路由,如/users对应GET/POST、/users/{id}对应GET/PUT/PATCH/DELETE,method必须显式声明且路径占位符{id}自动提取为$params['id']。

Wave Router 的 add 方法怎么写 RESTful 路由
Wave Router 本身不内置 RESTful 路由语法(比如 Laravel 的 Route::resource()),得靠手动组合 add 调用 + HTTP 方法约束来模拟。核心是:一个资源路径,对应多个 add,每个绑定不同 method 和回调。
常见错误是只写一次 add 却想处理所有方法,结果 GET 请求进来,POST 却 404;或者漏了 method 参数,导致所有方法都命中同一个 handler。
-
add第二个参数必须是数组,且含method键,值为字符串或数组(如['GET', 'HEAD']) - RESTful 常见映射:
/users→ GET 列表、POST 新增;/users/{id}→ GET 单条、PUT/PATCH 更新、DELETE 删除 - 路径中的
{id}是占位符,Wave Router 会自动提取为$params['id'],无需正则手动匹配
router->add('/users', ['method' => 'GET', 'handler' => [$userController, 'index']]);
router->add('/users', ['method' => 'POST', 'handler' => [$userController, 'store']]);
router->add('/users/{id}', ['method' => 'GET', 'handler' => [$userController, 'show']]);
router->add('/users/{id}', ['method' => ['PUT', 'PATCH'], 'handler' => [$userController, 'update']]);
router->add('/users/{id}', ['method' => 'DELETE', 'handler' => [$userController, 'destroy']]);
为什么 method 必须显式声明,不能靠请求自动识别
Wave Router 默认不读取原始请求方法——它只解析 URL 路径,method 完全依赖你传入的配置。如果你没写 method,它就默认接受所有方法,这在 REST 场景下极危险:比如一个本该只响应 DELETE 的路由,可能被 GET 意外触发。
更隐蔽的问题是,某些前端发 PUT/PATCH 请求时实际走的是 POST + X-HTTP-Method-Override 头,Wave Router 不处理这类模拟方法,必须由你中间件提前转换,或改用原生 $_SERVER['REQUEST_METHOD'] 判断后转发。
立即学习“PHP免费学习笔记(深入)”;
- 不声明
method→ 路由始终匹配,失去方法隔离能力 - 声明为单个字符串(如
'PUT')→ 严格匹配,PATCH会 405 - 声明为数组(如
['PUT', 'PATCH'])→ 更符合 REST 实践,但注意 handler 内部仍需判断具体是哪个方法
路径参数 {id} 提取失败的三个常见原因
看似简单的占位符,实际运行中常拿不到值,多数不是 Router 问题,而是调用链断在了前面。
- URL 中写了
/users/123,但路由定义是/users/{id}/(结尾多斜杠)→ 不匹配,$params为空 - 用了
addPattern自定义正则但没覆盖数字类型,比如{id:\w+}会拒绝纯数字123 - 没调用
dispatch()或调用前已输出内容(header 已发送)→ Router 内部抛异常但被静默吞掉,$params根本不会注入到 handler
调试时直接在 handler 里打 var_dump($params) 最快,别猜。
如何让 Wave Router 支持 OPTIONS 预检和 405 Method Not Allowed
Wave Router 不自动生成 OPTIONS 响应,也不自动返回 405。REST API 要合规,这两项得自己补。
- 对每个资源路径,额外加一条
OPTIONS路由,手动设置Access-Control-Allow-Methods头 - 在 dispatch 后检查是否匹配到路由但方法不匹配 → 此时手动 throw 新的
HttpException(405)(需提前定义) - 别依赖“没匹配到就 404”,因为方法错但路径对时,Router 默认返回空响应,前端收不到 405
router->add('/users/{id}', ['method' => 'OPTIONS', 'handler' => function () {
header('Access-Control-Allow-Methods: GET, PUT, PATCH, DELETE, OPTIONS');
exit;
}]);
真正难的不是写这几行,是确保所有资源路由都统一处理 OPTIONS 和 405,漏一个,前端跨域请求就卡住。











