PHP 8.4 未新增常量语法,define() 和 const 行为不变;所谓“新常量”实为属性访问器(如 public string $name { get => ...; set => ...; })和不对称可见性(如 public private(set)),作用于类属性而非常量;唯一影响常量的改动是支持 #[\Deprecated] 标注类常量。

PHP 8.4 没有新增“常量语法”,define() 和 const 两种定义方式依然有效,且行为未变。所谓“新常量语法”是常见误传——实际是 PHP 8.4 引入了**属性访问器(Accessors)** 和 **不对称可见性(如 public private(set))**,它们作用于**类属性**,不是常量。混淆往往来自对 public string $name { get => ...; set => ...; } 这类写法的误读。
为什么你会看到“常量式写法”却不是常量
这是属性访问器的声明语法,不是定义常量:
-
public string $name { get => ucfirst($this->value); }中的$name是**可读写的类属性**,不是常量;get只是控制读取逻辑,底层值仍可被修改(除非配合private(set)) - 它不满足常量的核心约束:不可变、无作用域限制、不能是对象或数组等复合类型
- 若你尝试在
get中返回固定字符串(如get => "v1.0"),那只是 getter 的返回值恒定,属性本身仍是可变容器,和const或define()完全不同
PHP 8.4 中真正影响常量的改动只有这一处
PHP 8.4 新增了 #[\Deprecated] 属性,现在可以标注**类常量**为废弃:
class ApiVersion
{
#[\Deprecated("Use V2 instead")]
public const V1 = 'https://api.v1.example.com';
<pre class="brush:php;toolbar:false;">public const V2 = 'https://api.v2.example.com';}
- 调用
ApiVersion::V1时会触发E_DEPRECATED警告(仅当启用error_reporting包含该级别) - 该特性仅适用于用户定义的类常量、函数、方法、类常量;不支持
define()定义的全局常量 - 注意:
#[\Deprecated]是属性(attribute),不是语法糖,必须带方括号,且命名空间反斜杠不能省略
别把 public private(set) 当成“只读常量”
这种写法控制的是**属性写入权限**,不是常量语义:
立即学习“PHP免费学习笔记(深入)”;
class Config
{
public string $host = 'localhost';
public private(set) string $port = '8080'; // ✅ 允许读,禁止外部赋值
}
-
$config->port = '9000'会报Fatal error: Cannot assign to property - 但
$config->port仍可在类内部被修改(比如在方法里),也不阻止serialize()或反射绕过 - 它和
const PORT = 8080;有本质区别:后者编译期固化、内存只存一份、无法通过任何方式修改 - 如果你真需要运行时常量(即初始化后不可变的属性),目前唯一可靠方式仍是私有属性 + 只读 getter + 构造器赋值
最易被忽略的一点:PHP 8.4 的所有新特性都**不改变常量的不可变性模型**。任何试图用访问器模拟“动态常量”或“条件常量”的做法,都会在类型推导、静态分析(如 PHPStan)、IDE 补全和 opcache 优化中遇到意料外的行为——因为引擎层面根本不认为那是常量。



















