
php-hooks 库的 `apply_filters()` 默认仅返回最后一个回调的返回值;若需收集所有钩子的返回结果,须为每个回调注册独立钩子名,并通过循环分别调用 `apply_filters()`。
在使用 bainternet/PHP-Hooks 时,一个常见误区是认为多次对同一钩子名(如 'my_filter')调用 add_filter() 会形成“链式执行并累积返回值”。但实际上,该库的设计遵循 WordPress 风格钩子语义:同名过滤器(filter)是按优先级顺序依次执行,但每次 apply_filters() 调用仅传递并返回单个“累加值”——即前一个回调的返回值作为下一个回调的输入参数,最终只返回最后一次处理的结果。
因此,在您的原始代码中:
app_hooks()->add_filter('my_filter', fn($v) => { echo $v; return "x"; });
app_hooks()->add_filter('my_filter', fn($v) => { echo $v; return "y"; });第二次回调接收到的 $value 实际上是第一次回调返回的 "x"(而非原始字符串 'some value to be passed'),导致输出为 xy,且最终 $my_tabs[0] 仅为 "y"。
✅ 正确解法:为每个逻辑独立的处理器分配唯一钩子名,再显式循环调用:
立即学习“PHP免费学习笔记(深入)”;
// 注册两个不同名称的过滤器
app_hooks()->add_filter('my_filter_x', function ($value) {
echo $value . "\n"; // 输出: some value to be passed
return "x";
});
app_hooks()->add_filter('my_filter_y', function ($value) {
echo $value . "\n"; // 输出: some value to be passed
return "y";
});
// 分别触发,各自接收原始值,并收集全部返回
$my_tabs = [];
$hooks_to_apply = ['my_filter_x', 'my_filter_y'];
foreach ($hooks_to_apply as $hook_name) {
$my_tabs[] = app_hooks()->apply_filters($hook_name, 'some value to be passed');
}
print_r($my_tabs);
// 输出:
// Array
// (
// [0] => x
// [1] => y
// )⚠️ 注意事项:
- PHP-Hooks 不支持类似 apply_filters_ref_array() 或批量返回数组的原生机制;其核心仍是单值流式传递;
- 若业务逻辑强依赖“同一钩子名下多个处理器并行执行并汇总结果”,建议自行封装一层适配器,或改用更现代的事件总线(如 Symfony EventDispatcher);
- 钩子名应具备语义性(如 user_login_validation, user_login_response),避免硬编码字符串,便于维护与调试。
总结:不是“钩子没生效”,而是对 apply_filters() 的行为预期与库设计存在偏差。明确区分「单钩子多回调(链式)」与「多钩子并行调用(集合)」两种模式,是正确使用 PHP-Hooks 的关键前提。











