usort回调中直接访问外部变量会报“Undefined variable”错误,因为回调函数运行在独立作用域,不自动继承父作用域变量;匿名函数必须用use显式捕获变量,use($var)为值传递,use(&$var)为引用传递,且use列表不支持表达式、超全局数组或$this。

usort 回调里直接用外部变量会报 Undefined variable
因为 usort 的回调函数(无论命名函数还是匿名函数)运行在独立作用域里,它不会自动继承定义位置的局部变量。哪怕变量就在上一行声明,比如 $order_by = 'price';,在回调内部直接写 $order_by 就是未定义——PHP 不做隐式捕获。
匿名函数必须用 use 显式绑定变量
use 不是“导入”,而是创建快照:把当前值(或引用)复制进闭包对象内部。不加 use,闭包根本看不到那个变量。
-
function($a, $b) use ($order_by)→ 值传递,闭包内改$order_by不影响外面 -
function($a, $b) use (&$order_by)→ 引用传递,闭包内改会同步到外部(慎用,尤其在循环中) -
use列表里不能写表达式,比如use ($x + 1)直接语法错误 - PHP 7.1+ 禁止
use超全局数组($_GET、$_POST)、$this(除非先赋给普通变量再传)
循环中用 use ($i) 会导致所有闭包共享末次值
这是最常踩的坑。例如在 for 循环里生成多个排序回调:
for ($i = 0; $i < 3; $i++) {
$funcs[] = function() use ($i) { echo $i; };
}
foreach ($funcs as $f) $f(); // 输出:3 3 3,不是 0 1 2
原因:use ($i) 每次都绑定同一个变量的最终值,不是每次迭代的快照。
立即学习“PHP免费学习笔记(深入)”;
- 临时解法:用引用
use (&$i),但循环结束后$i已越界,风险高 - 推荐解法:立即执行闭包捕获当前值,如
function() use ($i) { return $i; }() - 更稳妥:抽成独立函数,或用
foreach显式解构键值对
类方法里用 usort 要注意 $this 不自动可用
即使在类的方法里写匿名函数,$this 也不会自动带进去。必须显式 use ($this),但 PHP 7.1+ 要求先赋值再传:
$self = $this;
usort($items, function($a, $b) use ($self, $order_by) {
return $b['data'][$order_by] <=> $a['data'][$order_by];
});
否则会报错或行为不可靠。另外,命名函数方式调用时,必须用数组语法:[$this, 'compareMethod'],不能只写 'compareMethod'。
use 绑定的变量就脱离原始作用域,变成闭包私有状态——这点容易被忽略,尤其在长期持有回调(比如注册为事件处理器)时,外部 unset 原变量不影响闭包,但引用绑定后若外部销毁,闭包访问可能出错。



















