php函数内直接使用全局变量会报undefined variable错误,因全局变量不自动进入函数作用域;正确做法是用global声明或$globals数组访问。

函数里直接用全局变量会报 Undefined variable
PHP 不像 C,不会自动把全局变量带进函数作用域。函数内未声明就直接写 $config,哪怕外面真有这个变量,也会触发 Undefined variable 警告(PHP 8.0+ 是 E_WARNING)。
常见错误现象:
- 在函数里写
echo $db_host;,但$db_host是在文件顶部定义的 —— 直接报错 - 误以为
include进来的配置文件里的变量“自然可用”,结果函数里访问不到
正确做法只有两种:
- 在函数开头加
global $db_host, $db_port;,显式绑定 - 改用
$GLOBALS['db_host']访问,不用声明,但写法略啰嗦
注意:global 绑定的是同名变量的引用,不是拷贝。改了 $db_host 就等于改了全局值。
& 符号不是“取地址”,而是创建变量别名
PHP 没有传统意义上的指针,& 做的是“引用赋值”,让两个变量名指向同一个 zval 内存块。这和 global 的机制底层一致,但使用场景不同。
容易踩的坑:
-
$a = 1; $b = &$a; $b = 2;→$a变成2,这是预期行为 -
$a = [1,2,3]; $b = &$a; unset($a);→$b依然存在且可用,因为refcount没归零 - 函数参数加
&$param是传引用,但调用时不能传字面量,比如foo(&$arr[0])合法,foo(&123)会报错
性能影响:引用避免了 zval 复制,对大数组或对象有明显收益;但滥用会导致逻辑难追踪,尤其是多个地方同时修改同一份数据。
静态变量 static 不是“全局变量”,只是跨调用保留值
static $counter = 0; 看起来像全局变量,但它只属于当前函数,外部完全不可见,也不会污染全局符号表。
使用场景很具体:
- 缓存计算结果,比如递归中避免重复初始化
- 记录函数被调用了几次,用于限流或调试
- 生成唯一 ID,配合
microtime()或计数器
关键区别:
-
static变量第一次初始化后,后续调用不再执行赋值语句(static $x = time();只在首次调用时取时间) - 它不共享给其他函数,哪怕函数名相同但来自不同文件,也是各自独立的
zval - 不能用
unset()销毁,只能重置为新值
超全局变量如 $_POST 为什么不用 global 声明
因为 $_POST、$_GET、$_SESSION 等是 PHP 内核注册的“超全局”符号,它们被硬编码进每个作用域的符号查找链路,引擎在解析变量名时会优先检查这些预设键。
所以你能在函数里直接写 $_POST['id'],不是语法糖,是运行时机制决定的。但要注意:
-
$_SESSION必须先调用session_start()才有数据,否则是空数组 - 直接修改
$_SERVER不会影响真实请求头,它只是快照 - 不要用
global $_POST;—— 语法合法但纯属多余,还可能掩盖你对作用域的理解偏差
真正容易被忽略的点是:所有超全局变量都是“写时复制”(copy-on-write)的,你对 $_POST 元素做引用赋值($data =& $_POST['user'];),改 $data 不会反向写回 $_POST,除非你明确再赋值回去。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











