PHP能否像C++一样使用回调?传递静态方法为回调报类未找到如何解决
问题原因
你当前的报错以及不符合依赖解耦要求的核心原因是:你传递的'A::foo'属于延迟解析的字符串类型回调,PHP只有在实际执行$fn(1,'test')的时候才会尝试解析这个字符串、查找对应的A类和foo方法,这就带来两个问题:
- 若执行回调时A类未在全局作用域加载(比如你的include路径错误、自动加载器失效),就会抛出Class A not found错误
- 隐含了B类执行时必须能感知A类存在的耦合,不符合你的解耦要求
解决方案
不需要修改A类和B类的代码,只需要在调用端将静态方法包装为闭包传递即可,闭包会提前捕获A类的调用上下文,B类执行回调时完全不需要感知A类的存在。
通用写法(兼容所有PHP 7+版本)
include_once(__DIR__.'/A.php'); // 建议用__DIR__拼接绝对路径,避免相对路径引入失效 include_once(__DIR__.'/B.php'); // 把A::foo的调用包装成匿名函数 B::doSomething(function(int $a, string $b) { return A::foo($a, $b); }); // PHP 7.4+ 可以用箭头函数简化写法 B::doSomething(fn(int $a, string $b) => A::foo($a, $b));
PHP 8.1+ 简化写法(一阶可调用语法)
PHP 8.1及以上版本支持一阶可调用表达式语法,可以直接生成闭包,写法更简洁:
include_once(__DIR__.'/A.php'); include_once(__DIR__.'/B.php'); B::doSomething(A::foo(...));
原有写法报错排查
如果坚持要用字符串形式的回调,可以先在调用B::doSomething之前加一行代码验证A类是否正确加载:
var_dump(class_exists('A'));
如果返回false,说明你的include_once路径错误,替换为__DIR__拼接的绝对路径即可解决。
内容的提问来源于stack exchange,提问作者rhavin
相关产品推荐
相关产品推荐

