为何PHP 8.4中array_diff()无法直接处理枚举数组,而in_array()等可正常工作?
为什么array_diff()无法直接处理枚举数组?
场景复现(PHP 8.4环境)
定义以下函数:
function test_array_diff($all, $filtered) { return array_diff($all, $filtered); }
function test_array_udiff($all, $filtered) { return array_udiff($all, $filtered, fn($item1, $item2) => $item1 != $item2); }
function test_in_array($all, $filtered) { $diff = []; foreach ($all as $case) { if (!in_array($case, $filtered, true)) { $diff[] = $case; } } return $diff; }
定义枚举类:
enum MyEnum { case FOO; case BAR; }
声明测试变量:
$all = MyEnum::cases(); $filtered = [MyEnum::BAR];
现象
调用test_array_udiff($all, $filtered)和test_in_array($all, $filtered)可得到预期结果,但调用test_array_diff($all, $filtered)会抛出致命错误:
Fatal error: Uncaught Error: Object of class MyEnum could not be converted to string
原因分析
array_diff()的核心逻辑是将数组元素转换为字符串后再做比较,它会尝试把每个元素转为字符串来生成哈希值、判断等值。而PHP枚举对象默认没有实现字符串转换逻辑,直接转换会触发错误。in_array()在启用true参数(严格比较模式)时,会使用严格类型匹配(===),直接对比枚举对象的实例身份和枚举值,不需要转换为字符串,因此能正确处理枚举数组。array_udiff()支持自定义比较函数,你传入的匿名函数直接用!=对比枚举实例,枚举的!=操作会直接判断是否为同一个枚举case,不需要类型转换,所以可以正常工作。
简言之,array_diff()依赖字符串转换的特性,和另外两个函数的比较逻辑完全不同,这就是它无法直接处理枚举数组的根本原因。
内容的提问来源于stack exchange,提问作者Damien Garrido
相关产品推荐
相关产品推荐

