应使用 is_int($key) 或 is_string($key) 直接判断 foreach 遍历时获取的键类型;注意 JSON、$_GET 等来源的键恒为字符串,filter_var($key, FILTER_VALIDATE_INT) 可校验字符串是否实质等价于整数。

如何用 is_int() 和 is_string() 判断数组下标类型
PHP 数组的下标可以是整数或字符串,但 isset()、array_key_exists() 这类函数不区分类型,只看“是否存在”。真要识别下标类型,得对键本身做类型判断。
常见错误是直接 var_dump($arr) 看输出,误以为 0 和 "0" 是一样的键 —— 实际上它们在数组里共存且互不影响:
$arr = [0 => 'a', "0" => 'b']; var_dump($arr); // 输出两个元素:int(0) => 'a', string(1) => 'b'
- 遍历数组时,用
foreach ($arr as $key => $val)拿到的$key就是原始类型,可直接用is_int($key)或is_string($key)判断 - 注意:
is_numeric("0")返回true,但它不是is_int();别用is_numeric()替代类型判断 - 整数下标如
123、-5、0x1F(十六进制字面量)都算is_int();而"123"、"-5"、"0.0"都是字符串
为什么 array_keys() 返回的键可能全是字符串?
当你从 JSON 解析、表单提交或某些数据库驱动(如 PDO 默认 fetch mode)拿到数组时,下标常被强制转为字符串 —— 即使原始数据是数字。这不是 bug,是 PHP 类型隐式转换的结果。
-
json_decode('{"0":"a","1":"b"}', true)返回的数组,键是"0"、"1"字符串,不是整数 -
$_GET、$_POST所有键名永远是字符串,哪怕 URL 是?0=value - 用
array_keys($arr, null, true)不起作用 —— 第三个参数是搜索值是否严格匹配,和键类型无关
用 filter_var() 辅助识别“可安全转为整数”的字符串下标
有些场景你需要知道某个字符串键是否“实质等价于整数”,比如做索引校验或路由分发。这时 is_int() 太严格,is_numeric() 又太宽泛。
立即学习“PHP免费学习笔记(深入)”;
- 推荐组合:
is_string($key) && filter_var($key, FILTER_VALIDATE_INT) !== false - 它能正确拒绝
"12.3"、"0x10"、" 42 "(带空格)、"+42"(默认不认正号),但接受"-42"、"0" - 若需支持八进制或十六进制,得手动加
FILTER_FLAG_ALLOW_OCTAL/FILTER_FLAG_ALLOW_HEX,但多数业务不需要 - 性能上比
ctype_digit(ltrim($key, '-'))稍慢,但语义清晰、边界处理可靠
用 gettype() 查键类型时容易忽略的细节
gettype() 能返回 "integer" 或 "string",看起来万能,但实际有坑。
- PHP 8.0+ 中,
gettype(null)返回"null",但数组键不可能是null,所以这个情况可忽略 - 更关键的是:浮点数作为键会被自动转成整数或字符串 ——
[3.14 => 'x']等价于[3 => 'x'],而["3.14" => 'y']保留为字符串键。你永远拿不到gettype($key) === "double"的数组键 - 所以真正需要判断的,只有
integer和string两种;其他类型(如bool)作键也会被强转:[true => 'a']→ 键变成1(整数)
array_merge、json_encode)可能悄悄改变它。动手前先确认数据来源,比写一堆 is_* 更省事。











