array_filter 默认用松散比较过滤假值(如0、''、null),导致合法0被误删;需显式传回调如fn($v) => $v !== null && $v !== ''来精准过滤。

array_filter 为什么默认不删空字符串和 0
因为 array_filter 默认用的是「松散比较」逻辑:把每个值丢进 if 判断,''、0、0.0、null、false 全部被当成假值过滤掉——但很多人只想要真正意义上的「空值」(比如 null 或 ''),却意外把合法的 0 也干掉了。
常见错误现象:
输入 [1, 0, '', 'hello', null],用 array_filter($arr) 得到 [1 => 1, 3 => 'hello'],丢了 0 和空字符串,但业务里 0 可能是有效状态码。
- 如果只要剔除
null,用array_filter($arr, function($v) { return $v !== null; }) - 如果要剔除
null和'',但保留0、false、0.0,写成array_filter($arr, function($v) { return $v !== null && $v !== ''; }) - 注意:PHP 8.0+ 支持箭头函数,可简写为
array_filter($arr, fn($v) => $v !== null && $v !== ''),但老版本不兼容
array_filter 第二个参数 callback 传 null 的陷阱
写成 array_filter($arr, null) 看似省事,其实等价于没传回调——也就是走默认行为,还是按「真假值」过滤。这不是 bug,是设计,但容易误以为它会保留所有非空项(比如留着 0)。
- 想保留所有「非 null」且「非空字符串」?必须显式写回调,不能依赖
null -
array_filter($arr, 'strlen')是个常见替代方案,但它会把0(数字零)当字符串处理,strlen(0)返回1,所以0被留下;但strlen('')是0→ 过滤掉,strlen(null)触发 notice → 也被过滤。这个技巧有副作用,慎用 - PHP 7.4+ 中,
array_filter($arr, fn($v) => $v !== null)最直白安全
性能差异:filter vs foreach 手动遍历
对小数组(array_filter 和手动 foreach 几乎没差别;但大数组下,array_filter 内部做了内存预分配优化,通常比边循环边 unset 或 array_push 快 10%–20%。
立即学习“PHP免费学习笔记(深入)”;
- 别用
foreach + unset($arr[$k])原地删,PHP 数组键会乱,且性能差 - 如果还要保持原始键名(比如关联数组),
array_filter天然保留键;而array_values(array_filter(...))会重排索引,多一次遍历 - 极端场景(如超大数组 + 高频调用),可考虑用
ArrayIterator配合yield流式处理,但绝大多数情况没必要
PHP 版本兼容性与空值定义变化
PHP 8.0 引入了更严格的类型推导,但 array_filter 行为本身没变;真正要注意的是,不同 PHP 小版本对 null 和 '' 的判定始终一致,变的是你代码里怎么定义「空」。
- PHP 7.2+ 开始,
array_filter对NaN的处理更稳定,之前某些版本会把它当true留下 - 如果你在 Laravel 或 Symfony 项目里,别直接用
array_filter处理请求数据(比如request()->all()),框架自带的filter或collect(...)->filter()更安全,能自动跳过缺失字段 - 最易忽略的一点:JSON 解码后,
null字段进数组就是 PHPnull,但字符串"null"是字符串,不会被默认array_filter干掉——得自己加判断











