php 7.3 中函数不能直接更新外部变量,除非显式传引用;引用传递需在函数定义时用 &$var,调用时不可加 &;array_key_first/last、??=、get_defined_vars() 等均不改变外部变量。

PHP 7.3 中函数不能直接更新外部变量,除非显式传引用
PHP 默认按值传递参数,函数内部修改变量不会影响外部。想让函数“更新外部变量”,必须用引用传递(&$var),否则所有操作都只在函数作用域内生效。
常见错误现象:$a = 1; function modify($a) { $a = 2; } modify($a); echo $a; // 输出 1,不是 2
- 函数定义时加
&才算启用引用传递,调用时**不能**再写&(PHP 5.4+ 已禁止) - 仅支持变量传引用,
modify($x + 1)、modify(5)、modify(new stdClass())都会报 Notice 或 Fatal error - 数组元素、对象属性也可传引用,但需确保是可变左值(例如
$arr[0]可以,$arr['key'] ?? 0不行)
array_key_first / array_key_last 不改变原数组,也不需要引用
这两个 PHP 7.3 新增函数只是读取键名,不修改输入数组,因此完全不需要引用传递。它们返回的是字符串或 null,和外部变量是否被“更新”无关。
典型误用:$keys = array_key_first($data); —— 这里 $data 没被改动,$keys 是新变量,不是对 $data 的更新。
- 如果想基于首尾键做后续操作(比如删掉第一个元素),得自己调用
unset()或array_shift(),这些函数才可能影响原数组 -
array_key_first()和array_key_last()在低版本 PHP 中可通过reset() + key()/end() + key()模拟,但注意:它们会移动数组内部指针,而新函数不会
??= 运算符看似“更新”,实则只作用于变量本身
??= 是赋值运算符,它检查左侧变量是否为 null 或未定义,然后决定是否把右侧值赋给它。这不是函数调用,也不涉及引用;它直接修改目标变量的值。
例如:$config['timeout'] ??= 30; —— 如果 $config['timeout'] 不存在或为 null,就设成 30;否则什么也不做。这个动作发生在当前作用域,不依赖函数调用链。
- 不能对表达式使用:
($data['user']['name'] ?? 'anon') ??= 'guest'语法错误,因为左侧不是可赋值的变量(lvalue) - 数组嵌套深层键安全写法:先确保父级存在,再用
??=,例如$data['user'] = $data['user'] ?? []; $data['user']['role'] ??= 'member'; - 它和
isset()+ 赋值逻辑等价,但更紧凑;和||=不同,??=不会把0、false、''当作“空”来覆盖
get_defined_vars() 返回副本,修改它不影响原始变量
get_defined_vars() 返回当前作用域所有变量的**副本数组**,改这个数组里的值,比如 $vars['x'] = 999;,完全不会改变原始的 $x。
它常用于调试或日志记录,而不是变量批量更新手段。有人误以为能用它做“反射式赋值”,但 PHP 没提供反向写入接口。
- 若真需要动态更新多个变量,得用
extract()(有安全风险)或显式循环 +$$key = $value(需确认$key是合法变量名) -
extract()本身也不接受引用,它只是把数组键作为变量名,把值复制进去 - 任何试图绕过引用机制去“批量更新外部变量”的做法,都会遇到作用域隔离这个根本限制
最易被忽略的一点:PHP 的变量作用域和生命周期由引擎严格管理,所谓“函数更新外部变量”本质上只有两种合法路径——引用传递(&$var)或全局/静态变量访问。其他所有看起来像“更新”的行为,其实都是重新赋值或创建新变量。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











