最可靠方法是preg_match('/[\x{4e00}-\x{9fff}]/u', $str),需确保字符串为UTF-8编码且正则带/u修饰符,漏掉/u或编码不匹配将导致失效。

用 preg_match 判断字符串是否含中文最可靠
PHP 原生不提供“是否中文”的内置函数,is_string() 或 mb_detect_encoding() 都不能准确识别中文字符。真正能稳定工作的,是正则配合 UTF-8 编码范围:preg_match('/[\x{4e00}-\x{9fff}]/u', $str)。这个表达式匹配 Unicode 中文基本区(U+4E00–U+9FFF),覆盖绝大多数简体、繁体汉字,且 /u 修饰符确保按 UTF-8 处理。
常见错误是漏掉 /u,比如写成 preg_match('/[\x{4e00}-\x{9fff}]/', $str) —— 在 UTF-8 字符串下会完全失效,返回 false。
使用时注意:
-
$str必须是 UTF-8 编码,否则匹配结果不可靠;可通过mb_check_encoding($str, 'UTF-8')预检 - 单个汉字就满足条件,无需整字段都是中文;如需“全中文”,改用
^[\x{4e00}-\x{9fff}]+$ - 该正则不包含中文标点(如《》、【】)、日文假名或平假名,有需要得额外扩展
用 array_filter 筛选含中文的数组元素
直接对数组逐项判断并过滤,array_filter 是最自然的选择。它默认保留回调返回 true 的项,无需手动遍历或重建索引。
立即学习“PHP免费学习笔记(深入)”;
示例:
$arr = ['apple', '苹果', '123', '测试', 'hello'];
$chinese_items = array_filter($arr, function($v) {
return is_string($v) && preg_match('/[\x{4e00}-\x{9fff}]/u', $v);
});
// 结果:['苹果', '测试'],键名保留原样
关键点:
- 必须加
is_string($v)判断,避免对数字、null、数组等非字符串类型调用preg_match报 Warning - 若需重置键名(变成 0,1,2…),后续加
array_values($chinese_items) - 性能上,对大数组无明显瓶颈;但若需高频执行,可提前把正则编译为
PREG_PATTERN_ORDER常量缓存(实际收益极小,通常不必)
中文筛选失败?先检查这三件事
很多“筛不出中文”问题其实和正则无关,而是环境或数据本身出了问题:
-
PHP 文件本身不是 UTF-8 编码:编辑器保存为 ANSI 或 GBK,会导致源码里的中文字符串在运行时乱码,preg_match自然匹配不到 —— 用 IDE 查看文件编码并转为 UTF-8 without BOM -
数据库或接口返回的数据是 GBK/GB2312:即使页面显示正常,PHP 内部字符串仍是 GBK 字节流,/u正则无法解析 —— 统一转码:mb_convert_encoding($str, 'UTF-8', 'GBK') -
数组里混有 HTML 实体或转义字符:比如汉字或\u4f60\u597d,它们不是真实中文字符,需先解码:html_entity_decode($str, ENT_UNICODE, 'UTF-8')或json_decode('"'.$str.'"')
想筛“纯中文字符串”?正则和逻辑都要收紧
上面例子筛的是“含中文”,如果业务要求字段必须**全部由中文字符构成**(如用户名只允许汉字),就不能只用 [\x{4e00}-\x{9fff}],还得排除空格、字母、数字、标点等干扰。
推荐写法:
$pure_chinese = array_filter($arr, function($v) {
return is_string($v)
&& trim($v) !== ''
&& preg_match('/^[\x{4e00}-\x{9fff}]+$/u', $v);
});
这里 ^...+$ 保证首尾闭合,trim($v) !== '' 防止纯空白字符串误判。注意它仍不包含中文顿号、逗号、句号等标点 —— 若需支持,得显式加进字符组,例如:^[\x{4e00}-\x{9fff}、,。!?;:“”‘’()《》【】]+$。
真正难处理的是中英混排、带 emoji 或生僻字(如 U+3400–U+4DBF 扩展 A 区),这些场景建议引入专用库如 overtrue/pinyin 或自建 Unicode 范围表,而不是硬塞进一个正则里。











