array_key_exists('key', $array) 在数组有这个键时返回 true,没有时返回 false。注意参数顺序:键在前,数组在后。即使这个键下保存的值是 null,它也返回 true,这正是 isset() 做不到的一点。
如果要检查的是值而不是键,请使用 in_array()。
array_key_exists 与 isset 的区别
两者都检查键。只有当值为 null 时它们才会给出不同的结果:isset() 把 null 值当作“未设置”,array_key_exists() 则如实报告数组里有什么。
0 和 '' 对两者来说都算已设置;只有 null 会让它们产生分歧。该用哪一个,取决于 null 在你的数据中代表什么:
- 当
null表示“没有值”时,使用isset()。这是最常见的情况,它是语言结构(稍快一些),并且可以检查嵌套路径和未定义的变量而不产生警告。 - 当
null是一个真实的值、必须和缺失的键区分开时,使用array_key_exists():以null发送的 JSON 字段、值为NULL的数据库列、被显式设为null以清除的选项。
isset 页面介绍了它的其他用法,包括一次检查多个变量。
在 JSON 数据中区分 null 和缺失
一个只有 array_key_exists() 才能给出正确答案的典型场景:一个根据 JSON 更新记录的 API。以 null 发送的字段表示“清空它”,没有发送的字段表示“不要动它”。isset() 会把两者看成一回事。
如果用 isset($patch[$field]),电话号码会被保留下来,因为 null 看起来就像一个缺失的字段。
key_exists() 是同一个函数
key_exists() 是 array_key_exists() 的别名,是从早期 PHP 保留下来的。参数相同,结果也相同。建议使用完整的名字,因为读代码的人期望看到的是它。
键的类型:"1" 和 1 是同一个键
数组的键是整数或字符串,而内容是普通十进制整数的字符串会被存储为整数。所以 array_key_exists('1', $arr) 能找到键 1,反过来也一样。像 '01' 这样的字符串仍然是字符串,是另一个键。
检查嵌套键和多个键
array_key_exists() 只检查一层。对于嵌套路径,如果 null 无关紧要,isset($a['x']['y']) 可以一次检查所有层级。如果 null 有意义,就用一个简短的辅助函数逐层检查。要确认几个键是否都存在,可以和 array_diff_key() 的结果做比较。
array_flip($required) 把字段名列表变成键,这样 array_diff_key() 就能把它们和输入的键做比较;剩下的就是缺失字段的列表,可以直接用来生成错误提示。
对象要用 property_exists
旧版 PHP 允许把对象传给 array_key_exists(),PHP 8 则会抛出 TypeError。对于对象,property_exists() 检查已声明的或动态的属性(即使值为 null),而 isset($obj->prop) 的作用和数组上的 isset() 一样。
最后两行展示了另一种方式:get_object_vars() 把对象中可访问的属性变成一个数组,之后就可以使用数组函数了。
常见问题
为什么 array_key_exists 返回 true 时 isset 却返回 false?
因为这个键的值是 null。只有当键存在且值不是 null 时,isset($arr['k']) 才是 true;而只要键在数组里,array_key_exists('k', $arr) 就是 true。对于其他任何值,包括 0、'' 和 false,两者的结果都一样。
PHP 中的 key_exists 是什么?
它是 array_key_exists() 的别名。key_exists('id', $row) 和 array_key_exists('id', $row) 的行为完全相同。大多数代码使用较长的那个名字。
PHP 中怎样检查嵌套的键是否存在?
逐层检查:isset($data['user']['address']['city']) 一次检查整条路径,某一层缺失时也不会产生警告。如果 null 值也必须算作存在,就用 array_key_exists() 一层一层地检查。
可以对对象使用 array_key_exists 吗?
不可以。从 PHP 8.0 开始,传入对象会抛出 TypeError。对于已声明的属性,使用 property_exists($obj, 'name'),或者使用 isset($obj->name)。