Laravel日志报UTF-8字符格式错误无法定位出错文件如何解决?
报错根因说明
该异常为Laravel处理响应时,待序列化为JSON的数据中存在非UTF-8编码的字符,json_encode执行失败抛出的异常。栈轨迹全为框架内核代码无业务代码,是因为异常触发在响应格式化的最终阶段,并非业务代码执行过程中直接抛出。
排查思路
- 先定位触发报错的请求/任务
从当前栈轨迹的调用流程来看,报错为HTTP接口请求触发,而非队列任务触发(队列任务的错误栈会包含队列调度相关代码)。可先给路由增加全局中间件,记录所有请求的路由地址、请求参数、请求IP、操作用户ID等信息,和日志的报错时间做匹配,优先定位到具体是哪个接口触发的错误。
若后续排查到队列任务也触发同类报错,可给队列任务增加全局失败监听,记录所有失败任务的类名、入参、执行时间,匹配错误日志定位问题任务。 - 校验目标接口的返回数据编码
定位到接口后,逐点排查返回数据的来源:- 检查数据库读取的字段:优先排查从非UTF-8编码的旧库迁移过来的字段,以及存储了emoji、特殊符号、二进制内容的字符串字段,可用
mb_check_encoding($value, 'UTF-8')对返回字段逐个做编码校验 - 检查第三方依赖返回的内容:如果接口内调用了外部服务接口、读取了非UTF-8编码的本地文件/上传文件内容,这类外部输入未做编码转换也会触发该异常
- 检查数据库读取的字段:优先排查从非UTF-8编码的旧库迁移过来的字段,以及存储了emoji、特殊符号、二进制内容的字符串字段,可用
- 临时兜底方案
定位问题期间可先加兜底逻辑避免持续报错,在app/Providers/AppServiceProvider.php的boot方法中添加如下代码:
use Illuminate\Http\JsonResponse; JsonResponse::macro('setData', function ($data) { // 递归转义所有非UTF8字符串 array_walk_recursive($data, function (&$value) { if (is_string($value) && !mb_check_encoding($value, 'UTF-8')) { $value = mb_convert_encoding($value, 'UTF-8', 'auto'); } }); return parent::setData($data); });
- 根因修复建议
问题定位后从源头修复:- 统一数据库的库、表、字段编码为
utf8mb4,避免存储阶段出现编码丢失 - 所有外部输入(用户输入、第三方接口返回、文件解析内容)都做UTF-8编码校验和转换后再存储、使用
- 禁止直接返回二进制资源、未序列化的对象等无法被JSON序列化的内容作为接口返回值
- 统一数据库的库、表、字段编码为
内容的提问来源于stack exchange,提问作者wutlu
相关产品推荐
相关产品推荐

