真正该记住的PHP预定义常量共7个:__FILE__、__DIR__、__LINE__、PHP_OS_FAMILY、PHP_SAPI、STDIN/STDOUT/STDERR;它们在路径处理、环境判断和CLI脚本中高频使用,其余查文档更高效。

PHP预定义常量里哪些真该记住
PHP内置的预定义常量分两类:全局可用的(如 PHP_VERSION、__DIR__)和扩展相关的(如 PDO::ATTR_ERRMODE)。真正需要日常记住的其实就十来个,其余查文档比硬背靠谱。
重点记这些:__FILE__、__DIR__、__LINE__、PHP_OS_FAMILY、PHP_SAPI、STDIN/STDOUT/STDERR。它们在路径处理、环境判断、CLI脚本中高频出现。
-
__DIR__比dirname(__FILE__)更快更安全,尤其在 symlink 场景下不会出错 -
PHP_SAPI === 'cli'是判断是否运行在命令行的最可靠方式,php_sapi_name()有缓存风险 -
STDIN在 Web SAPI 下是null,直接读会 Warning;用前先is_resource(STDIN)判一下
魔术常量不是变量,不能被动态拼接
像 __FUNCTION__、__CLASS__ 这类魔术常量,值由编译器在解析时写死,不是运行时计算出来的。这意味着你没法用字符串拼接去“构造”它们。
常见错误现象:$x = '__' . 'CLASS__'; echo $x; 输出的是字面量字符串 __CLASS__,不是当前类名。
立即学习“PHP免费学习笔记(深入)”;
- 所有魔术常量都必须原样写出,大小写敏感:
__METHOD__≠__method__ -
__TRAIT__在非 trait 中返回空字符串,不是报错,容易误判作用域 -
__NAMESPACE__在全局命名空间下是空字符串,不是'\'或'.',做路径拼接时得单独处理
__FILE__ 和 __DIR__ 在 require/include 链中的行为差异
__FILE__ 总是返回当前文件的**绝对路径**(PHP 5.3+ 自动 realpath),而 __DIR__ 是它的 dirname。但关键点在于:它们的值取决于「哪个文件里写的这行代码」,不是「谁调用了它」。
比如 A.php require 'B.php',B.php 里写 echo __FILE__;,输出的是 B.php 的路径,不是 A.php 的。
- 想获取被包含文件所在目录?直接在 B.php 里用
__DIR__就行,别试图从 A.php 传路径进来 - 如果 B.php 被 symlink 指向,
__FILE__返回的是 symlink 路径(PHP 8.0+ 默认 resolve,旧版需手动realpath(__FILE__)) - 依赖
__DIR__加载配置时,确保相对路径基准一致,别混用getcwd()—— 它受 CLI 执行位置影响,不稳定
扩展常量没加载就用会 fatal error
像 IMAGETYPE_JPEG、CURLOPT_URL、JSON_THROW_ON_ERROR 这些不是 PHP 核心常量,而是对应扩展启用后才注册的。没开 extension,直接用就是 Fatal error: Uncaught Error: Undefined constant。
常见场景:Docker 环境里忘了装 gd 或 curl 扩展,本地开发正常,线上炸了。
- 检查扩展是否加载:
extension_loaded('gd')或function_exists('imagecreatefromjpeg')比defined('IMAGETYPE_JPEG')更准(有些扩展常量延迟注册) -
curl_setopt($ch, CURLOPT_URL, $url)中的CURLOPT_URL必须扩展存在,否则报错;不能靠@抑制,那是语法错误层级 - Composer 包里如果硬依赖某个扩展常量,记得在
composer.json的require里加"ext-curl": "*"约束
最易被忽略的其实是常量的“生效时机”:魔术常量在编译阶段固化,预定义常量在模块初始化时注册,扩展常量则完全依赖 dl() 或配置加载顺序。跨环境部署时,别只看 PHP 版本,得盯住 php -m 输出的实际扩展列表。











