绝大多数时候用const,仅运行时动态定义才用define;const必须顶层或类中声明,define可放条件块;const支持命名空间和类,define注册全局常量;const值需编译期确定,define支持运行时表达式。

绝大多数时候该用 const——编译时解析、性能高、语义清、支持命名空间和类;仅当需运行时动态定义(如环境判断、函数返回值)才用 define。
const 不能写在 if / foreach / 函数里,define 可以
这是最常踩坑的点:const 是语言结构,必须在编译期就确定存在,所以它只能出现在文件顶层或类中。一旦放进条件块,PHP 直接报语法错误,不等运行。
-
if (true) { const DEBUG = true; }→ 解析失败,Fatal error -
if (getenv('APP_ENV') === 'dev') { define('LOG_LEVEL', 'debug'); }→ 合法,运行时执行 - 常见误用场景:想根据配置开关注册调试常量、按 PHP 版本分支定义兼容常量、在自动加载器里动态设路径——这些都只能靠
define
命名空间和类中必须用 const
define 在命名空间内调用,注册的仍是全局常量,不会自动加命名空间前缀;而 const 会严格遵循当前作用域规则。
-
namespace App; const DB_PORT = 3306;→ 实际常量名为App\DB_PORT -
namespace App; define('DB_PORT', 3306);→ 实际注册为全局DB_PORT,use const App\DB_PORT拉不到它 - 类中定义成员常量?
class Config { const CACHE_TTL = 3600; }✅;define('CACHE_TTL', 3600)❌(语法错误) - Composer 多包共存时,
define污染全局空间的风险真实存在,尤其当不同包都定义了VERSION或ROOT
值类型和命名灵活性:define 支持运行时表达式,const 只认静态值
const 要求右侧是编译期可求值的表达式;define 不管左边右边,只要运行时不抛错就行。
-
const ROOT = __DIR__;✅(__DIR__是编译期常量) -
const ROOT = dirname(__FILE__);❌(函数调用,编译期无法执行) -
define('CACHE_DIR', sys_get_temp_dir() . '/cache');✅(运行时拼接,只要sys_get_temp_dir()不返回 false 就行) for ($i = 0; $i ✅(动态名称,<code>const完全不支持)- 大小写控制:
define('ENV', 'prod', true)允许用env或Env访问;const ENV = 'prod';严格大小写敏感
“undefined constant” 报错不是语法问题,而是加载或作用域没对上
用了 const 却提示未定义,90% 不是写错了,而是没被正确加载或引用方式不对。
- 命名空间没写全:在
namespace App\Config;里定义了const DB_NAME = 'myapp';,外部必须用App\Config\DB_NAME或先use const App\Config\DB_NAME;,直接写DB_NAME就 undefined - 文件没加载:常量定义在
config/constants.php,但你忘了require它,或者 Autoloader 根本没覆盖这个路径 - PHP 版本陷阱:PHP 5.5 及以下不支持全局
const(只允许类中使用),若项目需兼容老版本,define是更稳妥的选择 - 重定义限制:
const定义后完全不可覆盖;define虽然也不允许重复定义(会触发E_NOTICE),但因是函数调用,更容易在多个 require 链路中意外触发
真正容易被忽略的是:const 的作用域绑定发生在编译阶段,而 define 的生效时机取决于执行顺序——这意味着在复杂 autoload 或条件加载逻辑中,define 常量可能“看似存在”,实则被后续同名定义覆盖或未执行到;而 const 一旦编译通过,就稳如磐石,但也因此缺乏 runtime 的应变能力。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











