TypedClassConstants 是 PHP 8.3 引入的类常量类型声明特性,解决类常量长期缺乏显式类型约束的问题,支持标量、array、对象等类型,强制值匹配并提升 IDE 和静态分析工具的类型识别能力。

TypedClassConstants 是什么,它解决什么问题
PHP 8.3 引入的 TypedClassConstants 允许你在类常量声明时显式标注类型,比如 public const int $COUNT = 42;。它不是给“静态属性”加类型(那是 PHP 8.4 的 TypedProperties 增强),而是为类常量(class constants)补上了缺失的类型声明能力。
此前你只能写 public const COUNT = 42;,运行时靠文档或 IDE 猜类型;现在可以强制约束:值必须匹配声明类型,否则报 TypeError,且 IDE 和静态分析工具(如 PHPStan、Psalm)能真正识别该常量的类型。
怎么声明带类型的类常量:语法和限制
声明方式很简单,但有几条硬性规则:
- 必须使用
const关键字,不能用static或final替代 - 类型标注写在
const之前,紧邻修饰符(public/protected/private) - 只支持标量类型、
array、bool、null、void(仅用于const void,表示“无值”,实际极少用)、以及对象类型(需运行时存在) - 不支持联合类型(如
int|string)和泛型(如Collection<int></int>),这些会触发解析错误
class Config
{
public const string NAME = 'app';
private const array FEATURES = ['cache', 'logging'];
protected const int MAX_RETRY = 3;
public const DateTimeInterface CREATED_AT = new DateTimeImmutable();
}
注意:CREATED_AT 这种对象常量要求右侧表达式是“编译期可求值”的——PHP 8.3 允许调用构造函数(前提是参数全为字面量或已定义常量),但不允许方法调用、变量插值或闭包。
PHP 8.5.12 RC 1 候选版修复 BZ2、DOM、PDO、Opcache/JIT 和扩展内存安全问题,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
立即学习“PHP免费学习笔记(深入)”;
常见报错和踩坑点
-
ParseError: Syntax error, unexpected token "const":说明你漏写了访问修饰符,PHP 8.3 不支持无修饰符的 typed const,必须写 public const string FOO = 'x';,不能写 const string FOO = 'x';
-
TypeError: Typed class constant ... must be of type X, Y given:赋值类型不匹配,比如声明 public const int COUNT = '1';,字符串字面量无法隐式转为 int
- IDE 显示类型为
mixed:确认你用的是支持 PHP 8.3 的 PhpStorm 2023.3+ 或 VS Code + intelephense v1.9+,旧版本解析器不认识该语法
-
ReflectionClass::getConstant() 返回值类型不变,仍是 mixed;要获取类型需用 ReflectionClassConstant::getType(),返回 ReflectionNamedType 实例
和 const 表达式、枚举的配合建议
ParseError: Syntax error, unexpected token "const":说明你漏写了访问修饰符,PHP 8.3 不支持无修饰符的 typed const,必须写 public const string FOO = 'x';,不能写 const string FOO = 'x';
TypeError: Typed class constant ... must be of type X, Y given:赋值类型不匹配,比如声明 public const int COUNT = '1';,字符串字面量无法隐式转为 intmixed:确认你用的是支持 PHP 8.3 的 PhpStorm 2023.3+ 或 VS Code + intelephense v1.9+,旧版本解析器不认识该语法ReflectionClass::getConstant() 返回值类型不变,仍是 mixed;要获取类型需用 ReflectionClassConstant::getType(),返回 ReflectionNamedType 实例TypedClassConstants 和 PHP 8.3 的 const expressions(允许在 const 右侧用简单表达式)可以共存,但要注意类型推导边界:
-
public const int OFFSET = 10 * 2;✅ 合法,字面量运算,类型明确 -
public const string PREFIX = <strong>DIR</strong> . '/data';✅ 合法,字符串拼接 -
public const array CONFIG = array_merge(['a'], ['b']);❌ 非法,array_merge是函数调用,不在 const 表达式白名单中
如果你需要一组强类型、有限取值的常量,优先考虑 enum(PHP 8.1+):它天然带类型、不可变、可迭代,比一堆 typed const 更安全。只有当值需要跨类复用、或依赖外部配置(如从 env 读取并 cast)时,才用 TypedClassConstants。
类型检查发生在类加载阶段,而不是实例化时;这意味着哪怕你从没 new 过这个类,只要 autoloader 加载了它,类型校验就已执行。这点容易被忽略——它让错误暴露得更早,但也意味着你要确保所有 typed const 的右侧表达式在加载时绝对可求值。


















