本文目录导读:

在 PHP 8.3 中,常量类型(Typed Constants) 是一个重要的新特性,它允许你在定义类常量、接口常量、trait 常量以及全局常量(define() 函数)时,显式声明常量的数据类型。
核心语法
// 类常量(最常用)
class MyClass {
public const int MAX_ITEMS = 100;
public const string APP_NAME = 'MyApp';
}
// 接口常量
interface MyInterface {
public const string INTERFACE_NAME = 'MyInterface';
}
// trait 常量
trait MyTrait {
public const float PI = 3.14159;
}
// 全局常量(使用 define)
define('int', 100);
// 注意:全局常量使用 define() 时,类型声明放在第二个参数后面(不太自然)
define(constant_name: 'SITE_URL', value: 'https://example.com');
// PHP 8.3 的 define() 本身不支持直接写类型,上面的写法有问题。
// 正确写法(PHP 8.3 允许常量类型用于 define,但语法是新的)
define('int', 100); // 这仍然是旧语法,没有类型。
// PHP 8.3 中 define() 支持类型? PHP 8.3 并没有为 define() 添加类型声明。
// 所以以上是错误的,正确的全局常量类型声明只能用于类常量。
// 重新说明:
// 实际支持的写法(仅在类、接口、trait 内):
class MyClass {
public const int MAX = 100; // 正确
// public const string? NAME = null; // 不允许 nullable(联合类型也不行?暂时不行)
// public const int|string ID = 123; // 不允许联合类型(仅基本类型 + readonly?)
}
重点说明
-
支持的类型:PHP 8.3 常量类型支持的标量类型包括:
boolintfloatstringarray(必须为常量数组字面量)null(PHP 8.3 允许null作为类型,但常量必须为null,如果声明null类型则只能赋值null)
-
不支持的类型:
void、never、callable(因为常量不能是函数或可调用对象)object(常量不能是对象实例)- 联合类型(
int|string不允许) - 交集类型(
A&B不允许) - 可空类型(
?int不允许,但可以用int|null?也不行,因为联合类型不支持) mixed不支持
-
强制执行:如果赋值的常量值与声明的类型不匹配,PHP 8.3 会抛出 TypeError 错误(不仅警告)。
class Foo { public const int VALUE = 'hello'; // TypeError }
-
继承与覆盖:
如果子类覆盖父类的常量,子类常量的类型必须与父类兼容(或相同),如果能不写类型,则允许不写;如果写了,必须兼容。
代码示例
<?php
class Configuration {
// 标量类型
public const bool DEBUG = true;
public const int MAX_RETRIES = 3;
public const float TIMEOUT = 30.5;
public const string APP_NAME = 'MyApp';
public const array COLORS = ['red', 'green', 'blue'];
// 允许 final 修饰符(已有)
final public const string VERSION = '1.0';
}
// 错误用法
// class BadClass {
// public const int VALUE = 'not int'; // TypeError
// }
// 可空 null 类型
class NullableConst {
public const null NULL_CONST = null; // 只能赋值 null
// public const null INVALID = 1; // 会报 TypeError
}
echo Configuration::DEBUG; // 输出 true
echo Configuration::MAX_RETRIES; // 3
与 PHP 8.2 及之前的区别
| 特性 | PHP 8.2 及之前 | PHP 8.3 |
|---|---|---|
| 类常量类型声明 | 不支持(只能通过 PHPDoc 暗示) | 支持(语法错误级) |
| 类型检查 | 无静态检查(运行时弱类型转换) | 严格类型检查(抛出 TypeError) |
| 定义语法 | const VALUE = 42; |
const int VALUE = 42; |
实际开发建议
- 类常量:推荐在需要确保常量类型一致时(如配置项、枚举类)使用类型声明,提高代码健壮性。
- 全局常量(
define()):PHP 8.3 没有为define()添加类型声明,仅在类/接口/trait 内有效。 - 与
final结合:可以同时使用final和const防止子类覆盖,final public const int SIZE = 10;。 - 向后兼容:旧代码无需修改,未加类型声明的常量行为不变(仍然会自动类型转换,如
const A = '1'但实际赋值给int上下文时不会报错,因为没声明类型)。
PHP 8.3 的常量类型是一个实用的类型安全增强,尤其适合接口、配置类、枚举(配合 final)等场景,虽然目前支持的类型有限(仅标量 + null + array),但它为未来的 PHP 版本打下了更好基础,建议你在新项目中使用,并配合 IDE 的类型检查,可以早期发现潜在的常量赋值错误。