define() 是运行时定义常量,支持条件分支和函数内调用;const 是编译时指令,必须在顶层作用域声明,且 PHP 7.0+ 支持类外数组常量而 define() 不支持。

define() 和 const 定义常量的行为差异
用 define() 定义常量是运行时行为,可以在条件分支、循环甚至函数内部调用;而 const 是编译时指令,必须出现在顶层作用域(不能在 if、function 或 for 块里),否则会报 Parse error: syntax error。
两者都只接受标量值(字符串、整数、浮点、布尔),但 PHP 7.0+ 允许 const 在类外定义数组常量,define() 仍不支持。
-
define('API_TIMEOUT', 30)✅ 可在任意位置 -
const API_TIMEOUT = 30✅ 顶层可用 -
if (true) { const X = 1; }❌ 解析失败 -
define('CONFIG', ['host' => 'localhost'])❌ 报 Warning:Constant expression contains invalid operations
变量名带 $ 和常量名不带 $ 的实际影响
这不是命名习惯问题,而是语法层面的硬性区分:PHP 解析器看到 $ 就按变量处理,没 $ 就尝试匹配已定义常量,匹配失败则当作字符串字面量(并触发 E_NOTICE)。
比如写 echo DB_HOST;,如果没定义过 DB_HOST 常量,输出就是字符串 "DB_HOST",不是空或报错——这容易掩盖拼写错误。
立即学习“PHP免费学习笔记(深入)”;
- 检查是否存在:用
defined('DB_HOST'),别依赖isset($DB_HOST)(那是查变量) - 动态取值:用
constant($name),不能写$$name(那是可变变量,只对变量有效) - 误写
echo $DB_HOST;却忘了定义常量?结果是空输出,比 NOTICE 更难排查
作用域限制带来的真实踩坑场景
变量受作用域严格约束,常量没有——但这不意味着“随便用就安全”。常见陷阱是:在函数内改全局变量靠 global 或 $GLOBALS,但常量一旦定义,连 include 进来的文件也能直接读,无法隔离。
比如配置文件 config.php 里写了 define('ENV', 'prod'),被多个模块 require 后,谁都无法覆盖它。想换环境?只能提前判断是否已定义,或改用变量 + 条件加载。
- 函数内无法用
define()覆盖同名常量,第二次调用直接返回false -
const在命名空间中定义时,名称自动带命名空间前缀,而define()的名称是纯字符串,需手动拼接 - 测试时想 mock 常量?基本做不到,得靠预加载或扩展(如
phpunit的define()替换机制)
传值 vs 传址对常量和变量的根本约束
变量能传址($b = &$a),是因为它背后是内存引用;常量不行——它压根不占变量槽,只是编译期替换的符号标记。所以你永远不能对常量取地址、不能引用赋值、不能用 & 修饰。
这也解释了为什么常量不能是数组或对象:它们需要运行时内存分配和管理,而常量在脚本启动后就固化为不可变值。
- 写
$arr = [1,2]; $ref = &$arr;✅ 合法 - 写
define('LIST', [1,2]); $ref = &LIST;❌ 语法错误 - 试图修改
LIST[0] = 99?直接 Parse error,连运行都不让进



















