array_filter无法递归处理多维数组,需手动实现递归逻辑;基础版本保留0和"0",严格版本兼容array_filter默认行为,推荐使用可配置回调的匿名函数方案。

直接用 array_filter 无法递归处理多维数组,它默认只作用于当前层级。要过滤掉多维数组中所有空元素(包括空字符串、null、false、0、空数组等),需手动实现递归逻辑。
理解“空元素”的判定标准
PHP 中 array_filter($arr) 默认使用“宽松布尔判断”:会把 0、"0"、false、null、[]、"" 都当作“空”过滤掉——但有时你可能想保留 0 或 "0"。所以先明确需求:
- 若需严格过滤「真正无意义的空值」,建议自定义回调函数,区分
0和"" - 若接受默认行为(即 PHP 的隐式布尔转换),可简化递归逻辑
- 空数组
[]在递归中需特别处理:先递归清理子数组,再判断清理后是否为空
基础递归过滤函数(保留 0 和 "0")
以下函数只移除 null、false、纯空字符串 ""、空数组 [],但保留 0、"0"、" " 等:
function array_filter_recursive($arr) {
$result = [];
foreach ($arr as $key => $value) {
if (is_array($value)) {
$filtered = array_filter_recursive($value);
if (!empty($filtered)) { // 子数组递归清理后非空才保留
$result[$key] = $filtered;
}
} elseif ($value !== null && $value !== false && $value !== '') {
$result[$key] = $value;
}
}
return $result;
}
兼容默认 array_filter 行为的递归版本
如果希望和 array_filter() 完全一致(即 0、false、null、""、[] 全部视为“空”),可用此版本:
function array_filter_recursive_strict($arr) {
$result = [];
foreach ($arr as $key => $value) {
if (is_array($value)) {
$filtered = array_filter_recursive_strict($value);
// 再次用 array_filter 判定子数组是否“空”(兼容其逻辑)
if (array_filter($filtered)) {
$result[$key] = $filtered;
}
} elseif (array_filter([$value])) { // 单元素数组过 array_filter 判定
$result[$key] = $value;
}
}
return $result;
}
⚠️ 注意:array_filter([$value]) 是安全判断单值是否“非空”的方式,避免直接用 if ($value) 导致 "0" 被误判。
更简洁且可配置的写法(推荐)
用匿名函数 + 引用传参,支持自定义过滤条件:
$recursiveFilter = function($arr, $filterFn = null) use (&$recursiveFilter) {
$filterFn = $filterFn ?: function($v) { return $v !== null && $v !== false && $v !== ''; };
$result = [];
foreach ($arr as $k => $v) {
if (is_array($v)) {
$v = $recursiveFilter($v, $filterFn);
if (!empty($v) || call_user_func($filterFn, $v)) {
$result[$k] = $v;
}
} elseif (call_user_func($filterFn, $v)) {
$result[$k] = $v;
}
}
return $result;
};
// 使用示例:保留 0 和 "0"
$clean = $recursiveFilter($multiArray);
// 使用示例:完全模仿 array_filter 行为
$clean = $recursiveFilter($multiArray, function($v) {
return is_array($v) ? !empty(array_filter($v)) : (bool) $v || $v === '0' || $v === 0;
});
实际使用时,建议根据业务明确「哪些值必须保留」,再定制回调,避免过度过滤造成数据丢失。

















