这不是语法错误,而是PHP将未加引号的SOME_CONSTANT当作常量名查找,因未定义而触发Notice或Warning;echo 'SOME_CONSTANT'是字符串字面量,无需查找,故不报错。

直接说结论:这不是语法错误,而是 PHP 把你漏写引号的字符串当成了常量名去查找,结果没找到——所以它报的是 Notice 或 Warning,不是 Fatal Error。
为什么 echo SOME_CONSTANT; 会报错,但 echo 'SOME_CONSTANT'; 不会
PHP 在解析 echo SOME_CONSTANT; 时,会先查有没有叫 SOME_CONSTANT 的常量;没找到,就抛出 Notice: Use of undefined constant SOME_CONSTANT,并“假设”它是个字符串字面量(即自动转成 'SOME_CONSTANT')继续执行。这种行为在 PHP 7.4 及更早是 Notice,在 PHP 8.0+ 默认升级为 Warning,且某些严格上下文(如函数参数、数组键)会直接中断执行。
常见触发场景:
- 把数组下标写成
$_GET[uid]而不是$_GET['uid'] - 把配置项写成
define('DEBUG', true); if (DEBUG) { ... }却忘了提前define() - 拼写错误,比如定义了
MAX_RETRY,却写了MAX_RERTY - 在命名空间里用了全局常量,没加反斜杠,如
PDO::MYSQL_ATTR_INIT_COMMAND应写成\PDO::MYSQL_ATTR_INIT_COMMAND
defined() 是最安全的兜底检查方式
当你无法 100% 确保某个常量一定已定义(比如插件可选加载、条件编译),别硬用,先判断:
立即学习“PHP免费学习笔记(深入)”;
if (defined('API_TIMEOUT')) {
$timeout = API_TIMEOUT;
} else {
$timeout = 30;
}
注意:defined() 只接受字符串字面量或变量,不能传表达式;且大小写敏感,defined('API_TIMEOUT') 和 defined('api_timeout') 是两回事。
数组键、函数参数里写错常量名会直接失败
PHP 8.0+ 对这类误用更严格。例如:
// ❌ PHP 8.0+ 会 Warning 并可能跳过后续逻辑
$where = $db->where('status = ?', PUBLISHED);
// ✅ 正确写法:要么确保常量存在,要么改用字符串
$where = $db->where('status = ?', \PUBLISHED); // 如果是类常量
$where = $db->where('status = ?', 'published'); // 如果只是值
容易踩的坑:
-
define('ENV', 'prod');后,在switch(ENV)中漏掉引号,PHP 就去找常量ENV,而不是字符串'prod' - 第三方库更新后删掉了旧常量(如
MYSQL_ATTR_INIT_COMMAND在新版 PDO 中已弃用),代码没同步改,就会报Undefined class constant - 用
error_reporting(E_ALL & ~E_NOTICE)掩盖问题,上线后遇到 PHP 版本升级(如从 7.4 升到 8.2),突然大面积挂掉
真正要盯住的,不是怎么关提示,而是哪一行、哪个标识符被当成了常量——报错信息里的文件路径和行号比任何配置都可靠。尤其在升级 PHP 大版本后,这类问题会集中暴露,优先扫一遍 Notice: Use of undefined constant 的堆栈,比调 php.ini 更治本。



















