backedenum必须显式声明底层类型(如enum e: string)才支持->value,纯枚举仅支持->name;::cases()返回实例数组,取名称或值需配合array_column();反查用户输入应始终用tryfrom()而非from()。

直接用 ->name 和 ->value 拿标识和值,但得先分清是不是 backed enum
纯枚举(unit enum)只有 ->name,没有 ->value;只有声明了 enum E: string 或 enum E: int 的 backed enum 才有 ->value。硬写 Status::Draft->value 会报 Fatal error: Cannot access value property on unit enum case。
常见错误是定义时漏掉冒号和类型,比如写成 enum Status { case Draft; } 却在别处试图读 ->value。要读值,必须显式声明底层类型。
- 需要存数据库或传给 API?选
: string或: int - 只做状态分类、无外部映射?用纯枚举更轻量,也避免误用
->value -
->name始终可用,且是只读属性,不能赋值
遍历所有选项别手写数组,用 ::cases() + array_column()
Status::cases() 返回的是枚举实例数组,不是字符串列表。直接 print_r(Status::cases()) 看到的是一堆对象,不直观。
想取全部名称(比如填下拉框):用 array_column(Status::cases(), 'name');想取全部值(backed enum):用 array_column(Status::cases(), 'value')。
- 别用
get_class_vars()或反射——没必要,::cases()是官方正路 - 别在迁移里直接传
Status::cases()给 Laravel 的enum()字段——它要字符串数组,不是对象数组 - Laravel 迁移中正确写法是:
array_column(Status::cases(), 'value')或array_column(Status::cases(), 'name'),取决于你字段存的是语义名还是底层值
从用户输入反查枚举,死守 ::tryFrom(),别碰 ::from()
::from() 匹配失败直接抛 ValueError,HTTP 请求、表单提交、JSON 解析这类场景根本没法兜底;::tryFrom() 失败返回 null,可控。
典型错误是把 $_GET['status'] 直接喂给 Status::from(),一来非法值就崩。必须先判空:
$status = Status::tryFrom($_GET['status'] ?? '');
if ($status === null) {
throw new InvalidArgumentException('Invalid status');
}
-
::tryFrom()只对 backed enum 有效,unit enum 没这个方法 - 字符串匹配区分大小写,
tryFrom('DRAFT')对case Draft = 'draft'返回null - 整型 backed enum 中,
tryFrom('200')能匹配case OK = 200(PHP 自动类型转换),但tryFrom(200.0)不行
加方法别往枚举里塞实例方法,用静态方法或 trait 封装逻辑
PHP 枚举不允许定义实例方法,写 public function label() 会直接报 ParseError: Enum cases cannot have methods。所有行为逻辑得靠静态方法或外部 trait。
比如要支持中文标签、判断是否为终态,推荐用 trait 复用:
trait EnumHelper {
public static function labels(): array {
return match (static::class) {
Status::class => ['Draft' => '草稿', 'Published' => '已发布'],
default => [],
};
}
}
- 别在枚举里写
match($this)实例逻辑——语法不支持 - 静态方法里可以用
match分支,但得手动维护映射,无法自动同步::cases() - 如果逻辑复杂或需依赖服务容器,干脆抽到独立的
StatusService类里,别硬塞进枚举
最易被忽略的一点:枚举的类型安全只在运行时生效,IDE 和静态分析工具(如 PHPStan)对 match 的穷尽性检查依赖你显式列出所有 case。漏一个,既不报错也不警告——得靠测试覆盖或自定义 PHPStan 规则来兜底。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











