PHP 8.3 引入类型化类常量(Typed Class Constants),语法为 const type NAME = value,支持标量、联合类型、类名或 null,不支持 array 等;动态访问需用 ClassName::{$name},继承时类型必须严格兼容。

PHP 8.3 没有叫 TypedClasses 的函数——这个名称不存在,也不是官方 API 的一部分。所谓“类型化类”是误读,实际指的是「类型化类常量(Typed Class Constants)」,它是一种声明语法,不是可调用的函数。
Typed class constants 不是函数,而是声明语法
你不能「调用」TypedClasses,因为它根本不是函数名、扩展名或内置工具。PHP 8.3 中的类型化常量是通过 const type NAME = value 这种声明形式启用的:
- 只支持在
class、interface、trait、enum中使用 - 类型可以是标量(
string、int)、联合类型(string|int)、类名(Foo)或null - 不支持
array、callable、object等泛型或运行时类型
示例:
interface Config {
const string API_HOST = 'api.example.com';
const int TIMEOUT = 30;
}
class Service implements Config {
const string API_HOST = 'api.prod.com'; // ✅ 兼容 string 类型
// const int API_HOST = 'wrong'; // ❌ Fatal error: Cannot use string as value for class constant
}
动态访问 typed 常量必须用 ClassName::{$name}
PHP 8.3 引入了新语法支持运行时获取常量值,但前提是该常量已正确定义(含类型);否则会触发类型校验失败,而非静默忽略:
立即学习“PHP免费学习笔记(深入)”;
- 旧方式
constant('ClassName::CONST_NAME')仍可用,但绕过类型检查,不推荐 - 新方式
ClassName::{$var}在访问时会强制执行类型约束 - 若
$var是非法常量名(如不存在或类型不匹配),直接报Fatal error,不是Warning
错误示例:
class A {
const string MODE = 'dev';
}
$name = 'MODE';
echo A::{$name}; // ✅ 输出 'dev'
$name = 'MISSING';
echo A::{$name}; // ❌ Fatal error: Uncaught Error: Undefined constant A::MISSING
类型化常量在继承/实现中必须严格兼容
这是最容易踩坑的地方:一旦父接口或抽象类声明了 const string FOO,子类重定义时哪怕值合法,类型写错也会中断运行:
- 子类不能省略类型声明(即使父类写了)
- 不能用更宽泛的类型替代(如父类是
string,子类写string|int❌) - 联合类型必须完全一致(
string|null≠string|false) - 枚举成员作为常量值时,其底层类型也需匹配(例如
enum Status: string的成员可赋给const string STATUS)
常见报错信息:
Fatal error: Cannot use array as value for class constant Foo::CONFIG of type string
不要混淆 #[AllowDynamicProperties] 和类型化常量
有人把「允许动态属性」和「类型化常量」混为一谈,其实二者毫无关系:
-
#[AllowDynamicProperties]是控制能否在对象上写未声明属性(如$obj->new_prop = 1),与常量无关 - 类型化常量只作用于
const关键字声明的编译期值,不涉及对象实例 - 两者都强化类型安全,但生效时机、作用域、错误级别完全不同
如果你在调试时看到 E_DEPRECATED 提示动态属性被弃用,那和 const string FOO 是否生效完全无关——别试图用它“修复”常量类型问题。



















