如何将Callable数组合并为单个Callable?第三方库回调扩展方案
解决方案
1. Callable数组合并方案
你之前用字符串拼接合并回调的方式完全错误,PHP的callable是特殊类型(可匿名函数、对象方法数组、静态方法字符串等),不能直接用.拼接。正确做法是创建闭包函数,在闭包内遍历所有回调并依次执行。
修改子类before方法如下:
/** * @var callable[] */ private array $beforeCallbacks = []; public function before(callable $fn): ChildrenClass { $this->beforeCallbacks[] = $fn; // 创建合并后的回调:按顺序执行所有保存的回调 $mergedCallback = function(...$args) { foreach ($this->beforeCallbacks as $callback) { // 用展开运算符传递调用时的参数(PHP 5.6+支持) call_user_func($callback, ...$args); // 兼容低版本PHP可替换为:call_user_func_array($callback, $args); } }; return parent::before($mergedCallback); }
每次添加新回调后,会生成包含所有历史回调的新闭包,传递给父类before方法。父类执行该闭包时,会按顺序调用所有你添加的回调。
2. 为回调注入参数
根据需求不同,可通过调整闭包内的参数传递逻辑实现参数注入,分两种场景:
场景1:给所有回调注入相同固定参数
比如要给每个回调注入当前类实例$this或固定配置值:
$mergedCallback = function(...$args) { foreach ($this->beforeCallbacks as $callback) { // 合并固定注入参数与原调用参数 $fullParams = array_merge([$this, 'fixed_config'], $args); call_user_func($callback, ...$fullParams); } };
场景2:给每个回调注入不同自定义参数
若需为每个添加的回调单独指定注入参数,可修改存储结构,将回调与对应注入参数绑定保存:
/** * @var array[] 每个元素格式:['callback' => callable, 'inject' => mixed[]] */ private array $beforeCallbacks = []; public function before(callable $fn, array $injectParams = []): ChildrenClass { $this->beforeCallbacks[] = [ 'callback' => $fn, 'inject' => $injectParams ]; $mergedCallback = function(...$args) { foreach ($this->beforeCallbacks as $item) { // 先传递自定义注入参数,再传递调用时的动态参数 $fullParams = array_merge($item['inject'], $args); call_user_func($item['callback'], ...$fullParams); } }; return parent::before($mergedCallback); }
使用示例:
$obj->before(function($customParam, $dynamicArg) { echo $customParam . ' ' . $dynamicArg; }, ['my_custom_param']);
内容的提问来源于stack exchange,提问作者LordF
相关产品推荐
相关产品推荐

