在PHP脚本里,标识符主要分为变量和常量两类。变量用美元符号引导,代表内存中可被替换的数据容器;常量通过语言结构或函数登记,登记后值不可变。搞清二者差异,是写出可维护PHP代码的基础。

一、PHP变量的定义与底层机制
PHP变量以 $ 开头,后面接字母或下划线,再跟若干字母数字下划线。解释器在运行时把变量名登记进当前作用域的符号表,指向一个 zval 结构。zval 内部记录值类型、值本身以及引用计数。当多个变量赋同一个字面量时,默认采用写时复制,只有其中一个被修改才真正分离内存。
下面演示最基础的变量声明与重新赋值。注意变量名区分大小写,$Name 与 $name 是两个不同容器。
<?php $price = 100; // 整数型变量 $price = 99.9; // 同一变量改为浮点 $msg = '库存不足'; echo $price, $msg; ?>
1.1 变量作用域规则
在全局层面定义的变量,在函数内部默认不可见,必须使用 global 关键词引入,或者通过 $GLOBALS 超全局数组访问。函数内用 static 修饰的变量,会在多次调用间保留值,但仅限该函数局部可见。
错误地在函数里直接写外部变量名,是新手常见 bug。下面代码说明作用域隔离:
<?php
$count = 0;
function add() {
$count++; // 这里操作的是局部新变量,不影响全局
echo $count;
}
add(); // 输出 1
echo $count; // 输出 0
?>
1.2 可变变量与引用赋值
PHP支持可变变量,即变量名本身存于另一个变量中。引用赋值用 & 符号,让两个变量指向同一 zval,修改其一另一方同步变化。引用在遍历大数组时省内存,但容易引发意料外的联动修改。
<?php $a = 'hello'; $$a = 'world'; // 等价于 $hello = 'world' echo $hello; // 输出 world $b = 1; $c = &$b; $c = 5; echo $b; // 输出 5 ?>
二、PHP常量的定义与特性
常量默认区分大小写,推荐全大写加下划线命名。它一旦用 define 或 const 定义,就不能重新赋值或取消。常量没有美元符号,全局任何地方均可读取,不遵守变量作用域限制。
const 只能在类外顶层或类内部使用,编译期确定;define 可在条件语句中调用,运行期生效。下面的例子展示两种写法:
<?php
define('SITE_NAME', '我的博客');
const MAX_SIZE = 1024;
if (true) {
define('DEBUG', true); // 合法
// const TEMP = 1; // 位置错误会报编译异常
}
echo SITE_NAME, MAX_SIZE;
?>
2.1 常量与变量的存储差异
常量值通常存于独立的常量哈希表,请求结束前常驻。因为不可变,不存在引用计数与写时复制开销。把数据库表名、接口版本号写成常量,能防止业务逻辑里被误改,也方便全局检索。
若试图重定义已存在常量,PHP会发出警告并忽略第二次定义。使用 defined 函数可先检测再声明,避免上线环境报错。
<?php
if (!defined('API_URL')) {
define('API_URL', 'https://ipipp.com/api');
}
echo API_URL;
?>
2.2 类常量与魔术常量
类内部用 const 定义成员常量,通过 类名::常量名 访问。魔术常量如 __FILE__、__LINE__ 由解释器动态替换为位置信息,虽叫常量但随代码位置变化。它们对日志追踪特别有用。
<?php
class Config {
const TIMEOUT = 30;
}
echo Config::TIMEOUT;
echo '当前文件:' . __FILE__;
?>
三、标识符命名规范与全流程建议
无论是变量还是常量,标识符都不能以数字开头,不能含空格与大部分特殊符号。变量用小驼峰或下划线,常量用全大写下划线,是团队协作文档化的好习惯。避免使用 $l、$O 这类易混字符。
从定义到使用的标准流程应是:先规划哪些数据生命周期贯穿请求且不变,将其定为常量;其余随业务流动的数据用变量。在入口文件集中定义常量,业务函数内只声明局部变量,可减少全局污染。
| 对比项 | 变量 | 常量 |
|---|---|---|
| 前缀 | 需要 $ | 不需要 |
| 可变性 | 运行期可改 | 定义后不可改 |
| 作用域 | 受局部全局限制 | 默认全局 |
| 定义时机 | 随时赋值 | const编译期或define运行期 |
3.1 常见错误与排查
把常量当变量加美元符号,会得到未定义变量通知;在函数内未声明 global 就改外部变量,逻辑不生效。开启 error_reporting(E_ALL) 能提前暴露这类问题。用 get_defined_vars 和 get_defined_constants 可打印当前环境全部标识符辅助调试。
合理运用变量与常量,不仅让程序行为可预测,也降低后续重构成本。建议在代码评审时把常量集中度和变量命名清晰度作为检查项。