用 array_filter() 筛选超长字符串需根据编码选择 strlen() 或 mb_strlen(),含中文等必须用 mb_strlen($item, 'UTF-8') > 10 并显式指定编码,混入非字符串时应先 is_string() 校验,多条件筛选推荐 foreach 更可控。

用 array_filter() 配合 strlen() 或 mb_strlen() 筛选超长字符串
PHP 数组里存的如果是字符串,要按“字符长度”筛选超长项,array_filter() 是最直接的方式。关键在回调函数里判断长度——但必须注意编码:英文用 strlen() 没问题,含中文、emoji 时得用 mb_strlen(),否则会错判。
常见错误是写成 strlen($item) > 10 却没设 mb_internal_encoding('UTF-8'),导致中文算成 3 字节/字,结果漏掉本该被筛出的项。
- 限定值为 10 字符(非字节),且数组含中文:用
mb_strlen($item, 'UTF-8') > 10 - 纯 ASCII 场景(如 ID、token):用
strlen($item) > 10更快 - 回调中别直接用
return mb_strlen($item) > 10——mb_strlen()在未指定编码时依赖内部编码,不稳定
用 foreach 手动遍历 + mb_strlen() 控制逻辑分支
当筛选条件不止长度,还要同时记录索引、跳过空值或做类型校验时,foreach 比 array_filter() 更可控。尤其遇到 null、int、array 混入字符串数组时,mb_strlen() 会警告或返回 0,必须先 is_string() 判断。
示例场景:过滤用户昵称数组,只保留 UTF-8 编码下长度 2–12 的非空字符串:
立即学习“PHP免费学习笔记(深入)”;
foreach ($nicknames as $key => $val) {
if (!is_string($val) || trim($val) === '') continue;
if (mb_strlen(trim($val), 'UTF-8') >= 2 && mb_strlen(trim($val), 'UTF-8') <= 12) {
$valid[] = $val;
}
}
性能敏感场景下避免重复调用 mb_strlen()
如果数组很大(比如上万项),又多次用到同一字符串的长度,重复调 mb_strlen($item, 'UTF-8') 会明显拖慢速度。PHP 7.4+ 可用箭头函数缓存,但更稳妥的是在循环内存一次:
- 错:两次都调
mb_strlen($item, 'UTF-8') > 10 && mb_strlen($item, 'UTF-8') - 对:先
$len = mb_strlen($item, 'UTF-8');,再用$len > 10 && $len - 注意:
mb_strlen()对NULL返回0,不是 false,所以不能靠返回值真假判断是否为字符串
用 array_keys() + array_filter() 保留原始键名
array_filter() 默认会重排数字键,但业务常需保留原 key(比如关联数组里 key 是用户 ID)。这时不能只写 array_filter($arr, $callback),得加第三个参数 ARRAY_FILTER_USE_BOTH,并在回调里手动返回布尔值;或者更简单:先用 array_filter() 得到值,再用 array_keys() 反查原键。
推荐写法(保留键名,不重排):
$longItems = array_filter($data, function($item) {
return is_string($item) && mb_strlen($item, 'UTF-8') > 20;
}, ARRAY_FILTER_USE_BOTH);
这个写法容易被忽略的是第三个参数——缺了它,回调函数收不到键,也没法做键相关判断;写了它,函数签名必须接收两个参数($value, $key)。
实际用时最容易卡住的点,是没意识到mb_strlen() 的编码参数不是可选的“优化项”,而是决定结果正确性的必要条件。特别是从旧系统迁移或接第三方 API 数据时,表面看都是“字符串”,但底层编码一混,长度就全乱了。











