PHP 8.1 新增的枚举类型让代码中的固定值定义更加清晰规范,在实际开发中我们经常会遇到需要判断某个变量是否为枚举实例的场景,比如参数校验、逻辑分支处理等,选择正确的检测方式才能保证代码运行符合预期。

什么是 PHP 8.1 枚举实例
PHP 8.1 中的枚举分为纯枚举和回退枚举两种,枚举实例就是枚举类中定义的那些固定值,比如下面的颜色枚举,Color::RED、Color::GREEN都是枚举实例:
<?php
// 定义纯枚举
enum Color {
case RED;
case GREEN;
case BLUE;
}
// 定义回退枚举
enum Status: int {
case PENDING = 0;
case SUCCESS = 1;
case FAILED = 2;
}
?>判断枚举实例的常用方法
方法一:使用 instanceof 运算符
枚举实例本质上是枚举类的对象,所以可以直接使用instanceof运算符判断变量是否为某个特定枚举类的实例,这是最直观的方式:
<?php
enum Color {
case RED;
case GREEN;
}
$var1 = Color::RED;
$var2 = 'RED';
$var3 = new stdClass();
// 判断是否为Color枚举的实例
var_dump($var1 instanceof Color); // 输出 bool(true)
var_dump($var2 instanceof Color); // 输出 bool(false)
var_dump($var3 instanceof Color); // 输出 bool(false)
?>这种方法的局限性是只能判断是否为指定枚举类的实例,如果需要判断是否为任意枚举实例,就需要结合其他方式。
方法二:使用 is_a 函数
is_a函数和instanceof功能类似,同样可以判断变量是否为指定类的实例,也支持传入字符串形式的类名:
<?php
enum Status: int {
case PENDING = 0;
case SUCCESS = 1;
}
$var = Status::PENDING;
// 判断是否为Status枚举实例
var_dump(is_a($var, Status::class)); // 输出 bool(true)
var_dump(is_a($var, 'Status')); // 输出 bool(true)
?>方法三:结合反射判断是否为任意枚举实例
如果需要判断一个变量是否为任意枚举的实例,而不是指定某个枚举类,可以使用反射机制,先检查变量是否为对象,再判断其所属类是否为枚举类:
<?php
function isEnumInstance(mixed $var): bool {
// 不是对象直接返回false
if (!is_object($var)) {
return false;
}
// 使用反射判断所属类是否为枚举
$reflection = new ReflectionClass($var);
return $reflection->isEnum();
}
enum Color {
case RED;
}
enum Status: int {
case SUCCESS = 1;
}
$var1 = Color::RED;
$var2 = Status::SUCCESS;
$var3 = 'test';
$var4 = new stdClass();
var_dump(isEnumInstance($var1)); // 输出 bool(true)
var_dump(isEnumInstance($var2)); // 输出 bool(true)
var_dump(isEnumInstance($var3)); // 输出 bool(false)
var_dump(isEnumInstance($var4)); // 输出 bool(false)
?>不同方法的适用场景
不同检测方式有不同的适用场景,开发者可以根据实际需求选择:
- 如果明确知道需要判断的枚举类型,优先使用
instanceof或者is_a,性能更好,代码更简洁。 - 如果需要判断变量是否为任意枚举的实例,只能使用反射结合
isEnum方法的方式。 - 参数校验场景中,如果是强类型约束,可以直接在参数中声明枚举类型,PHP 会自动校验,不需要额外判断。
注意事项
使用枚举实例检测时需要注意几个问题:
枚举实例是单例的,同一个枚举值多次调用返回的是同一个对象,所以判断时不需要担心实例重复的问题。
另外,回退枚举的实例同样支持上述所有检测方式,和纯枚举的检测逻辑完全一致,不需要额外处理。如果使用的是低于 PHP 8.1 的版本,枚举类型不存在,所有相关检测代码都会报错,需要先确认运行环境版本。