PHP 8.4 扩展常量表达式支持:允许编译期静态求值的复杂表达式(如算术、数组合并、类型转换)、类常量支持类型声明与 readonly、define() 支持命名空间及动态作用域,但禁用用户函数、对象操作及非纯内置函数。
PHP 8.4 允许在 const、define() 和类常量定义中使用更复杂的表达式,只要它们在编译期能被静态求值。此前(如 PHP 8.3)只允许字面量、已知常量、简单算术和数组字面量;PHP 8.4 新增支持:
const MAX_RETRY = 3 * 2;
const FEATURES = ['log' => true, 'cache' => false] + ['metrics' => true];
const DEFAULT_TIMEOUT = (int) getenv('DEFAULT_TIMEOUT') ?: 5000;注意:getenv() 调用之所以可行,是因为 PHP 8.4 将其标记为「纯函数」——前提是环境变量在启动时已确定且未被修改。
PHP 8.4 允许在 const 声明中显式标注类型,并支持联合类型、readonly 修饰符和泛型约束(仅限于静态上下文):
class Config
{
public const int MAX_ITEMS = 100;
public const string|bool DEBUG_MODE = $_ENV['DEBUG'] ?? false;
public readonly const array STATUS_CODES = ['ok' => 200, 'err' => 500];
} 关键点:readonly const 表示该常量值不可被反射或扩展覆盖(即使通过 ReflectionClass::setStaticPropertyValue 也会失败),但不改变其作用域行为。
define() 在 PHP 8.4 中不再局限于全局命名空间或简单标识符。它现在接受完整命名空间路径,并可配合 __NAMESPACE__ 动态构造:
namespace App\Constants;这解决了过去必须用define(NAMESPACE . '\API_VERSION', 'v2.1'); define('App\Constants\IS_PRODUCTION', $_SERVER['APP_ENV'] === 'prod');
const 定义命名空间常量、却无法延迟求值的矛盾。但注意:define() 定义的常量仍不能用于 match 表达式的分支条件(因非编译期常量),而 const 定义的可以。
虽然表达式能力增强,但以下操作依然非法:
static::class)new、clone、yield 或闭包ini_get
()、function_exists())看似只读,但在 PHP 8.4 中仍未被标记为纯函数,因此不能出现在常量表达式中。遇到 ParseError: Constant expression contains invalid operations 时,优先检查是否误用了这类函数。