常量不可修改且全局可见,变量可变且作用域受限;常量无$符号、定义后不可撤销,变量必须带$、可随时重赋值;常量用于固定配置,变量用于动态数据。

常量不能改,变量随时能变
这是最根本的差异:一旦 define('DB_HOST', 'localhost') 或 const VERSION = '2.4.1' 执行成功,这个值在脚本生命周期内就锁死了;而 $db_host = 'localhost' 后还能写 $db_host = '127.0.0.1' —— 不报错,但可能悄悄破坏逻辑。
- 常见错误现象:把配置项写成变量(比如
$API_TIMEOUT = 5000),结果在某个函数里被意外覆盖,调试时发现超时时间突然变了 - 使用场景:数据库连接参数、API 版本号、状态码映射(如
const STATUS_ACTIVE = 1)这类不该动的值,必须用常量 - 注意:
define()和const都不可逆,PHP 不提供undefine()或unset_const()—— 别指望“取消定义”来补救
常量没有 $,变量必须带 $
这不是命名习惯问题,是语法铁律:DB_NAME 是合法常量名,$DB_NAME 就是另一个变量;漏掉 $ 写成 echo DB_NAME 能运行,但写成 echo $DB_NAME 却报 Notice: Undefined variable —— 因为它们压根不是同一个东西。
- 常见错误现象:复制粘贴变量代码时忘了删
$,或手抖多打了$,导致读到空值或触发 notice - 参数差异:
define()第一个参数是字符串('DB_NAME'),const直接写标识符(const DB_NAME = ...),别混用 - 性能影响:常量不经过符号表查找,直接解析,所以
echo SITE_URL比echo $site_url略快——但微乎其微,别为这点性能牺牲可读性
作用域完全不同:常量全局可见,变量看位置
在函数里 define('CACHE_TTL', 3600),外面照样能用 CACHE_TTL;但函数里声明的 $cache_ttl = 3600,出了函数就彻底失效。
- 常见错误现象:在类方法里用
$this->config['timeout']读配置,却忘了这个变量只在当前方法有效,下个方法就得重新赋值 - 使用场景:跨模块共享的开关(如
DEBUG_MODE)、项目级路径(ROOT_DIR)必须用常量,否则得靠全局变量或单例——更麻烦还易污染 - 注意:
const在类中定义的是类常量(Login::TRIES),它属于类作用域,不是“函数内定义就仅限函数内”,这点和define()的全局性不同
值类型限制:常量曾只支持标量,现在能存数组但有坑
PHP 5.6 开始支持 define('ROLES', ['admin' => 1, 'user' => 2]),PHP 7+ 还允许 const ROLES = ['admin' => 1] —— 但别高兴太早。
立即学习“PHP免费学习笔记(深入)”;
- 常见错误现象:用
define()定义数组常量后,在 PHP 5.5 或更老环境直接报错;或者误以为对象也能当常量值(define('LOGGER', new Logger())),PHP 会拒绝 - 兼容性影响:如果项目需支持 PHP define()(PHP 5.6+),
const数组只在 PHP 7.0+ 支持 - 容易被忽略的地方:即使 PHP 8.0+ 允许
const CONFIG = ['host' => DB_HOST]这种带常量表达式的写法,但DB_HOST本身必须已定义——顺序不能错,否则 fatal error











