PHP8递归截取多层数组字符串的核心是用array_map+匿名函数递归配合mb_substr(),需显式传'UTF-8'编码、跳过非字符串值、防止循环引用,并根据需求选择简洁匿名函数或带深度/键过滤的显式递归函数。

PHP8 中递归截取多层数组字符串的核心思路
直接用 mb_substr() 配合递归函数即可,关键不是“能不能递归”,而是“在哪一层截、截多少、是否保留结构”。PHP8 没有新增专门的递归截断函数,但 is_array() + array_map() 组合足够清晰可靠。
用 array_map + 匿名函数递归处理最简洁
适合绝大多数嵌套数组(含混合类型),代码短、可读性强、不污染全局作用域。注意必须显式处理非字符串值,否则 mb_substr(null, 0, 10) 会静默返回空字符串,容易掩盖数据问题。
$truncate = function ($value, $len = 10) use (&$truncate) {
if (is_array($value)) {
return array_map($truncate, $value, array_fill(0, count($value), $len));
}
return is_string($value) ? mb_substr($value, 0, $len, 'UTF-8') : $value;
};
$data = ['name' => '张三丰', 'desc' => ['bio' => '武当派创始人', 'quote' => '道可道非常道']];
$result = $truncate($data, 5); // ['name' => '张三丰', 'desc' => ['bio' => '武当派', 'quote' => '道可道']]
- 必须用
&$truncate引用自身,PHP8 不支持在array_map中直接写fn()递归(会报Undefined variable) -
mb_substr()第四参数'UTF-8'必须显式传入,PHP8 默认编码是UTF-8,但部分环境或旧配置可能 fallback 到ISO-8859-1,导致中文截断乱码 - 非字符串值(如
int、bool、null)原样返回,避免强制转字符串引发逻辑错误
遇到深层嵌套或需控制层级时改用显式递归函数
当需要限制只处理前 3 层、跳过某些键(如 id、created_at),或对不同键应用不同长度时,匿名函数不够灵活,得写带参数的普通函数。
function truncateArray($arr, $maxLen = 10, $depth = 0, $maxDepth = 5) {
if (!is_array($arr) || $depth > $maxDepth) {
return $arr;
}
$result = [];
foreach ($arr as $key => $value) {
if ($key === 'id' || $key === 'created_at') {
$result[$key] = $value;
continue;
}
$result[$key] = is_array($value)
? truncateArray($value, $maxLen, $depth + 1, $maxDepth)
: (is_string($value) ? mb_substr($value, 0, $maxLen, 'UTF-8') : $value);
}
return $result;
}
-
$depth和$maxDepth是防止无限递归的保险丝,尤其当数组存在引用循环(如$arr['parent'] = &$arr)时必不可少 - 跳过特定键的逻辑放在递归入口处,比在每层都
array_filter()更高效 - 不要用
json_encode()→ 截断 →json_decode(),那会丢失类型(int变成string)、破坏浮点精度、且无法处理资源或对象
常见错误:mb_substr 在非 UTF-8 字符串上截断出错
错误现象:中文变成问号、截出半个字符、长度计算不准。根本原因不是递归写错了,而是源字符串编码和 mb_substr() 声明的编码不一致。
立即学习“PHP免费学习笔记(深入)”;
- 先用
mb_detect_encoding($str, ['UTF-8', 'GB2312', 'GBK'], true)检测真实编码,再传给mb_substr() - 如果确定全是 UTF-8,但仍有乱码,检查是否被
iconv()或mb_convert_encoding()多次转换污染了字节流 - 不要依赖
mb_internal_encoding()全局设置——PHP8 默认是UTF-8,但某些框架或扩展可能中途修改它,显式传编码最稳



















