不能直接用if-else链匹配路径,因前缀重叠、动参提取缺失、中间件不可插拔、优先级难控;职责链通过handlerinterface的canhandle()与handle()分离匹配与执行,确保短路、组合与兜底。

为什么不能直接用 if-else 链匹配路径
写一堆 if (strpos($path, '/api/user') === 0) 看似简单,但很快会失控:路径前缀重叠(如 /api/users 和 /api/users/export)、动参提取缺失、中间件无法插拔、优先级难控制。职责链不是炫技,是把「谁该处理这个请求」的决策权从硬编码里抽出来。
HandlerInterface 必须定义的两个方法
每个处理器必须能判断是否“认领”当前请求,且能执行实际逻辑。接口只需两件事:
interface HandlerInterface
{
public function canHandle(string $path): bool;
public function handle(string $path): ?array; // 返回 [status, body] 或 null 表示不处理
}
注意:canHandle() 只做路径匹配(比如检查前缀、正则、或解析后比对路由表),不执行业务逻辑;handle() 才真正干活。漏掉这个分离,链就失去短路和组合意义。
链式调用时如何避免无限循环或漏匹配
常见错误是让每个 handle() 都无条件调用 $next->handle(),结果没一个返回非 null 值,最终崩掉或返回空响应。正确做法:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
-
canHandle()返回true时,handle()必须返回有效数组(哪怕[404, 'Not Found']) - 如果
canHandle()是false,才把请求往下传 —— 不是“我处理不了,你来”,而是“这根本不是我的职责范围” - 链尾必须有兜底处理器(比如匹配
'*'或空路径),否则未覆盖路径会返回null导致 HTTP 响应体丢失
示例链初始化:
$chain = new ApiUserHandler(); $chain = new ApiPostHandler($chain); $chain = new NotFoundHandler($chain); // 最后一个
动参提取别塞在 canHandle() 里
想从 /api/users/123 提取 id=123?别在 canHandle() 中用 preg_match() 解析并存到类属性——职责链强调无状态传递。正确方式:
- 在
canHandle()中只做轻量判断(如str_starts_with($path, '/api/users/')) - 在
handle()中用正则或explode()提取参数,再调用真实业务函数 - 如果多个处理器都要解析同类路径,抽一个
PathParser工具类,别让每个Handler重复写preg_match('@^/api/users/(\d+)$@', $path, $m)
否则你会在调试时发现:某个处理器的 canHandle() 里改了全局变量,下一个处理器拿到的是脏数据。
真正的难点不在拼链,而在设计每个 Handler 的边界——它该管几条路由?是否要支持 HTTP 方法区分?要不要提前校验 token?这些决策一旦模糊,链就会退化成带壳的 switch。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










