PHP 中变量声明位置决定其访问范围(作用域),主要分三类:
<?php
function foo() {
$local = "仅函数内可见";
echo $local;
}
foo(); // 正常输出
// echo $local; // 报错:未定义变量
?>
global $var 声明。$GLOBALS['var'] 实现。<?php
$global = "全局变量";
function bar() {
global $global; // 建立到 $GLOBALS['global'] 的引用
echo $global;
}
bar(); // 输出 "全局变量"
?>
static $var = 初始值 声明。static $a = strlen("abc") 会报错)。<?php
function counter() {
static $count = 0; // 仅首次执行初始化
$count++;
echo $count . "\n";
}
counter(); // 1
counter(); // 2
counter(); // 3
?>
类属性/方法用 static 修饰,作用域类似,但通过 类名::$prop、self::$prop、parent::$prop 访问,声明在方法外部。
PHP 引用(&)让不同变量名指向同一内存地址(Zend 核心实现“写时复制” Copy-on-Write)。
<?php
$a = "ABC";
$b = &$a; // $b 引用 $a
echo $a; // ABC
echo $b; // ABC
$b = "EFG";
echo $a; // EFG (受影响)
echo $b; // EFG
?>
函数定义参数加 &,调用时传入变量,函数内修改参数将影响外部变量。
<?php
function add100(&$num) {
$num += 100;
}
$val = 1;
add100($val);
echo $val; // 101
?>
函数声明加 &,调用时赋值也要加 &,才能得到变量引用而非值拷贝。
<?php
function &getStatic() {
static $b = 0;
$b++;
return $b;
}
$a = getStatic(); // 1,值拷贝
$a = 5;
$a = getStatic(); // 2,值拷贝
$a = &getStatic(); // 3,引用返回,$a 与静态 $b 绑定
$a = 5;
$a = getStatic(); // 6,$b 被修改为 5 后再 ++ 变 6
?>
规则:$a = &func() 才是引用返回,相当于 $a = &$b;普通 $a = func() 只是值拷贝。
<?php
$a = 1;
$b = &$a;
unset($a); // 仅解除 $a 与值的绑定,$b 仍持有值 1
echo $b; // 1
?>
unset 只断开变量名与值的绑定,不销毁值本身(引用计数归零才销毁)。
<?php
global $var; // 等价于
$var = &$GLOBALS['var'];
?>
PHP 5+ 对象默认按引用传递(实际是对象句柄的值传递)。对象方法中 $this 始终指向调用该方法的对象实例。
<?php
$a = 1;
$b = $a; // 此时 $a 与 $b 指向同一内存(引用计数=2),无拷贝
$a = "dsd"; // 发生写操作,Zend 自动为 $b 复制一份 $a 的旧值,重新申请内存
?>
此机制极大提升性能:仅读不写时共享内存,写入时才分离。
var aa = 'xxx' 在函数外声明 = 全局变量(无论是否带 var)。var 声明 = 局部变量;不带 var = 隐式全局变量(严格模式下报错)。& 引用传参,语义明确。&。