php 8.2 枚举是不可变对象,非类不可 new,操作应基于成员引用;backedenum 需用 from()/tryfrom() 还原标量值,访问 value/name 属性而非方法,遍历用 cases()。

PHP 8.2 的枚举不是“类”,不能用 new 实例化,也没有传统意义上的“枚举函数”可调用——你真正要操作的是枚举成员本身、它的值(value)、名称(name),以及配套的静态构造方法 from() 和 tryFrom()。
枚举成员本身就是对象,直接用 === 比较
纯枚举(无标量值)和 BackedEnum 的成员都是不可变的对象实例,不是字符串或整数。传参、判断、匹配都应直接使用成员引用。
- 错误写法:
if ($status === 'shipped')—— 类型不匹配,永远为 false - 正确写法:
if ($status === OrderStatus::Shipped) - 在
match中必须用完整成员路径:match($status) { OrderStatus::Pending => ..., ... } - 函数参数类型声明直接写枚举名:
function handle(OrderStatus $status): void
BackedEnum 必须用 from() 或 tryFrom() 从标量值还原
只有继承 BackedEnum(即定义时指定了 :int 或 :string)的枚举才支持从外部值(如数据库字段、API 请求参数)重建实例。这是最常被卡住的地方。
-
from():输入非法值会抛出ValueError,适合可信上下文(如配置文件读取)$code = HttpStatus::from(200); // OKHttpStatus::from(999); // 抛出 ValueError -
tryFrom():输入非法值返回null,适合处理用户输入或数据库脏数据$code = HttpStatus::tryFrom($_GET['status'] ?? null) ?? HttpStatus::OK; - 别试图用
(string)$enum或强制类型转换——会得到空字符串或 1,毫无意义
获取枚举的底层值或名称,别漏掉 ->value 和 ->name
BackedEnum 成员有 value 属性,所有枚举成员都有 name 属性。它们是只读属性,不是方法,不需要加括号。
-
OrderStatus::Shipped->value→ 返回'shipped'(若为stringbacked)或3(若为intbacked) -
OrderStatus::Shipped->name→ 总是返回字符串'Shipped',与定义时的 case 名一致 - JSON 序列化必须手动提取:
json_encode(['status' => $status->value]),直接json_encode($status)输出{} - 数据库存储通常存
value,查询后用tryFrom()还原,不要存name
遍历所有枚举项只能用 cases(),不能 foreach 枚举名
PHP 不允许 foreach (OrderStatus as $item) 这种语法。唯一标准方式是调用静态方法 cases(),它返回一个包含全部枚举成员的数组。
$all = OrderStatus::cases(); // array<orderstatus></orderstatus>- 可用于生成下拉选项:
array_map(fn($s) => ['value' => $s->value, 'label' => $s->name], OrderStatus::cases()) -
cases()对纯枚举和 BackedEnum 都有效,但纯枚举成员没有value属性,访问会报错 - 别写
getConstants()或反射枚举类——没这个必要,也容易出错
最容易被忽略的是:BackedEnum 的标量类型(int 或 string)在定义时就锁死,from() 的参数类型必须严格匹配;而 cases() 返回的是对象数组,不是值数组——想批量取 value 得显式映射。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











