
php-hooks 库的 `apply_filters()` 默认仅返回最后一个回调的执行结果;若需收集所有已注册同名钩子的返回值,必须手动遍历调用或改用支持“过滤器链聚合”的设计模式。
在 PHP-Hooks(bainternet/PHP-Hooks)中,add_filter() 允许为同一钩子名(如 'my_filter')注册多个回调函数,但其核心机制是链式传递:每个回调接收前一个回调的返回值作为输入,并最终只返回最后一个回调的结果。这与 WordPress 的 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"; });
$my_tabs[] = app_hooks()->apply_filters('my_filter', 'some value to be passed');实际执行流程为:
- 第一个回调接收 'some value to be passed',输出该字符串,返回 "x";
- 第二个回调接收 "x"(而非原始字符串),输出 "x",返回 "y";
- apply_filters() 最终只返回 "y" → $my_tabs = ['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";
});
// 手动批量触发不同钩子,收集全部返回值
$hook_names = ['my_filter_x', 'my_filter_y'];
$my_tabs = [];
foreach ($hook_names as $hook) {
$result = app_hooks()->apply_filters($hook, 'some value to be passed');
$my_tabs[] = $result;
}
print_r($my_tabs);
// 输出:
// Array
// (
// [0] => x
// [1] => y
// )⚠️ 注意事项:
- 不要依赖 apply_filters() 自动聚合多个同名回调的返回值——该库不提供类似 apply_filters_array() 的原生方法;
- 若业务逻辑强依赖“同一语义钩子下多处理器并行执行+结果合并”,建议自行封装工具函数,例如:
function apply_filters_all($hook, $value) { $hooks = app_hooks()->get_filters($hook); // 注意:需确认库是否暴露 get_filters() $results = []; foreach ($hooks as $callback) { $results[] = call_user_func($callback, $value); } return $results; }(注:PHP-Hooks 默认未公开 get_filters() 方法,如需此能力,需扩展类或修改源码)
? 总结:PHP-Hooks 是轻量级钩子实现,强调链式数据流而非事件广播。追求“多回调并行返回”时,请主动管理钩子命名与调用逻辑——这是设计使然,而非使用错误。











