PHP 变量是一个以 $ 开头的名字,给它赋值就创建了它:$name = "Ada";。PHP 没有声明关键字,也不用写类型,因为类型由值决定。之后还可以给它赋另一种类型的值。
变量命名规则
变量名以 $ 开头,接着是一个字母或下划线,后面可以跟任意字母、数字或下划线。非 ASCII 字母也算字母,所以 $名前 是合法的,不过通常还是用 ASCII 名字。变量名区分大小写。
| 名字 | 是否合法 |
|---|---|
$total、$userName、$user_name | 合法 |
$_count、$item2 | 合法 |
$2items | 不合法,不能以数字开头 |
$user-name | 不合法,这表示 $user 减去 name |
$this | 不合法,它保留给当前对象使用,给它赋值会导致致命错误 |
所以 $city、$City 和 $CITY 是三个不同的变量。可以用 snake_case($first_name)或 camelCase($firstName),同一个项目里坚持一种风格。PSR 编码规范有意没有规定变量的命名方式;Laravel 和 Symfony 的代码大多用 camelCase。
在字符串中使用变量
在双引号中,PHP 会把变量替换成它的值;在单引号中则不会。如果变量后面紧跟着字母,或者要用字符串键访问数组元素,就用花括号把变量括起来:
字符串页面详细介绍了引号、字符串拼接和变量插值。
未定义的变量和默认值
读取一个从未赋值的变量会得到 null,并且 PHP 会输出一条警告:
Warning: Undefined variable $discount in /home/index.php on line 3
可以先用 isset 检查,或者用空合并运算符 ?? 提供默认值。这两种方式都不会产生警告:
$x ??= 0; 是 $x = $x ?? 0; 的简写。表单和 URL 参数是最常见的场景:$page = $_GET['page'] ?? 1;。
函数中的变量作用域
在函数外定义的变量在函数内不可见,在函数内创建的变量在函数返回后就会消失。从 JavaScript 转过来的人最容易在这里栽跟头:
如果没有 ?? 0,第一个函数会对未定义的 $taxRate 发出警告。把值作为参数传入,可以让函数的行为可预测、易于测试,这也应该是你的首选做法。函数页面介绍了参数和返回值。
global 关键字和 $GLOBALS
如果函数确实必须使用全局变量,可以用 global 声明它,或者通过 $GLOBALS 数组访问,这个数组按名字保存了所有全局变量:
全局变量会让代码更难读懂,因为任何函数都可能修改它们。它们常见于旧代码和 WordPress 插件(global $wpdb;);在新代码中,应该把值传进去或者使用类。
静态变量会保留值
函数内的 static 变量只创建一次,并在多次调用之间保留它的值。它仍然是局部变量:函数外的代码看不到它。
可变变量($$name)
$$name 把 $name 的值当作另一个变量的名字。这样写可以运行,但用数组几乎总能更清楚地完成同样的事:
<?php
$field = "color";
$$field = "blue"; // creates $color
echo $color, "\n";
// The clearer way to have names chosen at runtime:
$settings = [];
$settings[$field] = "blue";
echo $settings["color"], "\n";
复制还是引用
把一个变量赋给另一个变量会复制它的值,数组也一样。在前面加上 &,两个名字就会指向同一个值:
对象的行为不同:赋值对象时复制的是指向同一个对象的句柄,所以通过任意一个变量所做的修改,在另一个变量上都看得到。要得到真正的副本,用 clone。
常见错误:在 if 或循环里设置的变量
PHP 没有块级作用域,所以在 if、for 或 foreach 里创建的变量在块结束后依然存在。这很方便,但也藏着一个 bug:如果块没有执行,变量就根本没有被创建。
如果没有设置默认值的那一行,$orders 为空时 $message 就是未定义的,并会输出警告。在可能给变量赋值的块之前,先给每个变量一个值。
常见问题
PHP 中怎么声明变量?
给一个以 $ 开头的名字赋值:$count = 10;。PHP 没有 var 或 let 关键字,声明时也不写类型;变量在第一次赋值时创建,类型由它的值决定。
为什么函数里看不到在外面定义的变量?
PHP 函数有自己的局部作用域,不会自动看到全局变量。可以把值作为参数传进去(最干净的做法),在函数内声明 global $name;,或者读取 $GLOBALS['name']。闭包可以用 use ($name) 捕获它,箭头函数 fn() 会自动捕获。
PHP 中的静态变量是什么?
在函数内用 static 声明的局部变量,例如 static $calls = 0;。它只初始化一次,并在该函数的多次调用之间保留值,很适合做计数器和简单的缓存。
PHP 变量名区分大小写吗?
区分。$name、$Name 和 $NAME 是三个不同的变量。不过 PHP 中的函数名和类名不区分大小写。
PHP 中怎么删除一个变量?
调用 unset($name);。之后 isset($name) 为 false,再读取它会出现 "Undefined variable" 警告。赋值为 null 则会保留变量,只是把它清空。