PHP数组中Unicode转HTML实体问题求助
解决PHP中Unicode字符导致json_encode异常及转HTML实体问题
我来帮你搞定这个Unicode字符处理的坑!首先咱们得先搞清楚问题出在哪:
问题根源
你用的utf8ize函数里的utf8_encode()其实是把ISO-8859-1编码转成UTF-8,但数据库里的长破折号(就是你看到的\u0096)大概率是Windows-1252编码的字符——这个编码里的0x96是长破折号,但在ISO-8859-1里它是个无意义的控制字符,所以用utf8_encode()转出来就会出现异常,甚至之前导致name字段直接变成null,也是因为原字符串编码和处理逻辑不匹配,json_encode无法解析。
解决方案步骤
1. 先从源头解决:确保数据库连接用UTF-8
这是最根本的办法,避免后续手动转码的麻烦。不管你用PDO还是mysqli,都要强制设置连接编码为utf8mb4(支持所有Unicode字符,包括emoji):
- PDO示例:
$pdo = new PDO( 'mysql:host=your_host;dbname=your_db;charset=utf8mb4', 'username', 'password', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION] );
- mysqli示例:
$conn = mysqli_connect('your_host', 'username', 'password', 'your_db'); mysqli_set_charset($conn, 'utf8mb4');
这样从数据库取出来的字符串本身就是正确的UTF-8,不用再手动转码,json_encode()也能正常处理name字段,不会返回null。
2. 修复utf8ize函数(如果必须手动转码)
如果因为某些原因没法改数据库连接编码,那咱们把转码逻辑换成更通用的mb_convert_encoding(),指定原编码为Windows-1252(根据你的数据情况调整,如果不确定可以用自动检测):
function utf8ize($d) { if (is_array($d)) { foreach ($d as $k => $v) { $d[$k] = utf8ize($v); } } elseif (is_string($d)) { // 把Windows-1252编码转成UTF-8,替换成你的实际原编码 $utf8Str = mb_convert_encoding($d, 'UTF-8', 'Windows-1252'); // 可选:如果需要把Unicode字符转成HTML实体 return htmlentities($utf8Str, ENT_QUOTES | ENT_HTML5, 'UTF-8'); } return $d; }
3. 单独处理HTML实体转换
如果只是想把特定字段(比如name)里的Unicode字符转成HTML实体,也可以单独处理:
// 遍历数组时处理每个元素的name字段 foreach ($arr as &$item) { if (isset($item['name']) && is_string($item['name'])) { // 先确保是UTF-8编码,再转实体 $utf8Name = mb_convert_encoding($item['name'], 'UTF-8', 'Windows-1252'); $item['name'] = htmlentities($utf8Name, ENT_QUOTES | ENT_HTML5, 'UTF-8'); } } echo json_encode($arr);
补充说明
json_encode()输出的\u0096其实是UTF-8字符的Unicode转义序列,前端是可以正常解析显示的,但如果要在HTML里直接显示,转成HTML实体(比如–对应短破折号,—对应长破折号)会更稳妥。- 用
mb_convert_encoding()的时候,一定要确认原字符串的编码是什么——如果不确定,可以试试mb_detect_encoding($d)自动检测,但自动检测可能有误差,最好还是从数据库或数据源确认编码。
内容的提问来源于stack exchange,提问作者wreckit
相关产品推荐
相关产品推荐

