array_filter() 是php中实际承担去空值任务的主力函数,但需注意其默认行为会误删0等有效值,应根据业务需求传入定制回调函数,并避免误用array_diff系列和empty/isset等非类型安全方案。

array_filter() 是唯一真正靠谱的内置方案
PHP 没有专门叫“去空值”的函数,array_filter() 是实际承担这个任务的主力。它默认会过滤掉所有被判定为 false 的值(包括 ''、0、0.0、null、false、[]),但这也正是最容易出错的地方——它不区分“空字符串”和“数字零”,也不管你是否想保留 0 这种有意义的值。
常见错误现象:
用 array_filter($arr) 后发现 0 消失了,或者 '0'(字符串零)也被干掉了。
- 如果只要去掉
null和'',保留0、false、[]:必须传回调函数,比如array_filter($arr, function($v) { return $v !== null && $v !== ''; }) - 如果想严格判断“空白字符串”,用
trim():array_filter($arr, function($v) { return is_string($v) ? trim($v) !== '' : $v !== null; }) -
array_filter()会重置键名,要保留原键用array_filter($arr, ... , ARRAY_FILTER_USE_BOTH)配合键判断
array_diff() 和 array_diff_assoc() 不是去空值工具
有人拿 array_diff($arr, ['']) 去“删空字符串”,这只能删掉值恰好等于 '' 的项,对 null、false、空白格组成的字符串(如 "
")完全无效。更危险的是 array_diff_assoc(),它比对键+值,一旦数组里有重复值或键顺序不同,结果就不可控。
-
array_diff($arr, [null])无效:因为null在松散比较中会被转成空字符串或0,行为不一致 - 所有
array_diff*系列函数本质是集合差集,不是类型感知的“判空”,别当过滤器用 - 性能上,它们要遍历对比整个参考数组,比单次回调的
array_filter()开销大得多
isset() 和 empty() 不能直接用于数组批量过滤
isset() 和 empty() 是表达式,不是数组函数,没法直接喂给 array_filter() 当回调用——因为 isset($v) 对 null 返回 false,但对未定义变量才报错;而 empty($v) 会把 0、'0'、[] 全判为空,语义太宽。
立即学习“PHP免费学习笔记(深入)”;
- 写
array_filter($arr, 'empty')看似简洁,实则等同于默认行为,且隐式类型转换风险更高 -
isset()在数组元素层面基本没用:数组元素不存在时本就会是null或触发 notice,不该靠它来“过滤” - 真要结合用,得明确封装逻辑,例如:
array_filter($arr, function($v) { return isset($v) && is_string($v) ? strlen(trim($v)) > 0 : !empty($v); })
注意 array_map() + array_filter() 组合的冗余开销
有人先用 array_map('trim', $arr) 再 array_filter(),看起来干净,但多了一轮遍历。如果原始数组很大,或者 trim() 调用本身有成本(比如含大量长字符串),这种写法会拖慢明显。
- 合并操作更高效:在
array_filter()回调里直接trim(),一次遍历搞定 - 如果还要去首尾空白+去全角空格,别用
trim(),改用preg_replace('/^[\s\x{3000}]+|[\s\x{3000}]+$/u', '', $v),但要注意 PCRE 性能 - PHP 8.0+ 可用
str_starts_with()/str_ends_with()替代部分trim()场景,但它们不处理中间空白,别误用
最麻烦的其实是“空”的定义本身——业务里要删的是 null?还是 ''?还是 "
"?还是 '0'?没想清楚这点,函数选得再对也白搭。











