PHP中json_encode遇特殊字符失效,array_map触发500错误求助
问题诊断与解决办法
为啥会触发500错误?
utf8_encode() 只能处理ISO-8859-1(Latin-1)编码的字符串,你直接用array_map批量处理整行数据,大概率踩了这些坑:
- 数据库返回的字段本身已经是UTF-8编码,强行转码会导致编码冲突报错
- 结果集里包含非字符串类型(比如整数、NULL、日期对象、二进制数据),
utf8_encode处理不了这些类型,直接抛出致命错误 - 字段里有ISO-8859-1无法表示的编码内容,转码过程触发错误
靠谱的解决思路
思路一:让sqlsrv直接返回UTF-8数据
这是最省心的根源解决办法,从数据库层面直接拿到UTF-8编码的数据,避免后续转码麻烦。sqlsrv支持在连接或查询时指定字符集:
- 连接数据库时添加
CharacterSet参数:
$connectionInfo = array( "Database" => "你的数据库名", "UID" => "用户名", "PWD" => "密码", "CharacterSet" => "UTF-8" // 关键配置项 ); $conn = sqlsrv_connect($服务器地址, $connectionInfo);
- 仅针对单个查询配置的话,执行语句时传入选项:
$options = array("CharacterSet" => "UTF-8"); $stmt = sqlsrv_query($conn, $sql语句, array(), $options);
思路二:安全地批量转码(仅当数据确实是非UTF-8时使用)
必须手动转码的话,先判断字段类型和编码,避免对非字符串内容瞎操作:
function safe_utf8_encode($value) { // 只对字符串且非UTF-8编码的内容进行转码 if (is_string($value) && !mb_check_encoding($value, 'UTF-8')) { return utf8_encode($value); } // 非字符串类型直接返回原内容 return $value; } if ($stmt) { if (sqlsrv_has_rows($stmt)) { while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $row = array_map('safe_utf8_encode', $row); echo json_encode($row); } } }
思路三:处理特殊字段类型
如果结果集里有NULL、sqlsrv返回的DateTime对象这类特殊值,utf8_encode根本无法处理,得先对这些类型做转换:
function prepare_for_json($value) { if (is_null($value)) { return null; } // 将DateTime对象转换为JSON兼容的字符串格式 if ($value instanceof DateTime) { return $value->format('Y-m-d H:i:s'); } // 字符串转码逻辑 if (is_string($value) && !mb_check_encoding($value, 'UTF-8')) { return utf8_encode($value); } return $value; } // 替换原有的array_map调用 $row = array_map('prepare_for_json', $row);
调试小技巧
开启PHP错误提示,直接查看500错误的具体原因:
error_reporting(E_ALL); ini_set('display_errors', 1);
比如会提示“utf8_encode() expects parameter 1 to be string, integer given”,一眼就能定位到是哪个字段类型出了问题。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

