PHP默认值必须是编译期可确定的常量表达式,仅允许标量字面量、null、数组字面量(PHP 5.6+)及已定义常量;变量、超全局数组访问、函数调用等运行时表达式均非法,否则在解析阶段直接报错。

因为PHP在解析函数定义时就要求所有默认值必须是“编译期可确定的常量表达式”,而变量在解析阶段根本还没被赋值,也不属于语言规定的静态上下文。
默认值必须在编译时就能确定
PHP解析器读到 function send($msg = $default) 这类写法时,会直接报错:Parse error: syntax error, unexpected '$default'。这不是运行时报错,而是代码根本过不了语法分析这关。原因在于:函数签名属于“声明”,不是“执行”,所有默认值必须像 100、'hello'、PHP_VERSION_ID 这样,在代码加载时就能算出结果。
- 合法:
$timeout = 30、$enabled = true、$list = [](PHP 5.6+) - 非法:
$host = $_SERVER['HTTP_HOST']、$now = time()、$cfg = $config['db']
超全局变量也不行
很多人以为 $_ENV['DB_HOST'] 或 $_POST['token'] 是“现成的值”,其实它们只是变量名,不是字面量。PHP不允许任何变量出现在默认参数位置,哪怕它是超全局变量或常量数组的键访问——这些操作都依赖运行时环境,无法在编译期求值。
想安全获取这类值?用空合并操作符在函数体内处理:$host = $_ENV['DB_HOST'] ?? 'localhost';
立即学习“PHP免费学习笔记(深入)”;
函数调用同样被禁止
function log($msg = get_default()) 看似合理,但 get_default() 是运行时行为,每次调用时机、返回值都可能不同。PHP强制要求默认值“无副作用、无依赖、无状态”。如果真需要动态默认值,应在函数体开头判断并赋值:
- 错误:
function connect($dsn = build_dsn()) { ... } - 正确:
function connect($dsn = null) { $dsn = $dsn ?? build_dsn(); ... }
那什么才算“安全的默认值”?
只有三类内容被允许:
- 标量字面量:
123、false、"abc"、3.14 - null 和数组字面量:
null、[](PHP 5.6+)、[1,2,3] - 已定义的常量:
DEFAULT_LIMIT、PHP_MAJOR_VERSION、__FILE__
不复杂但容易忽略。



















