<p>PHP匿名函数无法直接递归调用自身,需通过引用传递使函数获知自身引用,典型方式是用use(& $fn)绑定自身变量,如$factorial = function($n) use (& $factorial) { return $n

PHP匿名函数怎么调用自己
PHP匿名函数默认无法直接递归调用自身,因为没名字——$fn() 在定义时还不存在,写进去会报 Undefined variable: fn 或 Call to undefined function。核心解法是让函数“知道自己的引用”,靠的是引用传递 + 参数绑定。
最稳妥的方式是把匿名函数作为参数传给自己:
$factorial = function($n) use (&$factorial) {
return $n <= 1 ? 1 : $n * $factorial($n - 1);
};注意两点:use (&$factorial) 中的 & 是关键,必须引用传入,否则闭包捕获的是值(此时变量还没赋值完,为 null);$factorial 变量名需在定义前声明或在同一作用域可访问(如函数内、全局、类方法中)。
为什么不能只写 use ($factorial) 不加 &
不加引用会导致闭包捕获的是定义时刻 $factorial 的值——而那时它还没被赋值,是 null。运行时调用 $factorial($n - 1) 就变成 null(...),触发 Fatal error: Uncaught Error: Call to a null value。
立即学习“PHP免费学习笔记(深入)”;
-
use ($factorial)→ 捕获值(此时为null)→ 运行时报错 -
use (&$factorial)→ 捕获变量本身 → 后续赋值后能正确调用 - PHP 7.4+ 支持箭头函数,但箭头函数不支持递归(不能
use引用自身,语法也不允许)
在类方法里用匿名函数递归要注意什么
类作用域下,$this 和变量生命周期更复杂,直接 use (&$fn) 可能因对象销毁或作用域隔离失败。推荐显式绑定 $this 并确保变量在方法内声明:
<pre class="brush:php;toolbar:false;">class Math {
public function getRecursiveSum() {
$sum = null; // 先声明
$sum = function($n) use (&$sum) {
return $n <= 0 ? 0 : $n + $sum($n - 1);
};
return $sum;
}
}如果需要访问 $this->prop,得同时 <code>use ($this, &$sum);但要注意循环引用风险——$sum 持有 $this,$this 又可能持有 $sum,可能导致内存无法释放。
替代方案:用 Closure::bind 或普通命名函数
真要频繁递归,匿名函数不是最优选。更清晰的做法是定义命名函数,或用 Closure::bind 手动绑定作用域(极少必要):
比如想在闭包里调用自身但避免 use (&$x) 的写法,可以:
$fn = function($n) {
if ($n <= 1) return 1;
$self = Closure::bind(function($n) { return $n * $this($n - 1); }, $fn, null);
return $self($n);
};但这绕远了,且性能差、可读性低。实际项目中,该用命名函数就用命名函数——匿名递归适合一次性、简单逻辑,比如数组深度遍历的回调里临时用一下,别硬套。
真正容易被忽略的是:PHP 的 GC 对闭包引用链处理较保守,use (&$x) 一旦形成环,对象可能不会及时销毁。递归层级深时,务必确认没有意外的长生命周期引用滞留。



















