根本原因是输出流程被干扰,需在QRcode::png()后加exit终止脚本,并检查UTF-8无BOM编码、禁用输出缓冲、确保字体支持中文及数据全程UTF-8。

QRcode::png() 直接输出中文时乱码,根本原因不是“库不支持中文”,而是输出流程被干扰。绝大多数情况,加一句 exit 就能解决,但背后有三个必须检查的环节。
为什么 QRcode::png() 输出后扫出来是乱码或方块
这个函数本身会调用 imagepng() 并直接输出二进制图像流,但 PHP 脚本若未终止,后续代码(比如框架的视图渲染、自动输出的 HTML 标签、BOM 头、空格或换行)会被拼在 PNG 数据前面——浏览器收到的就是「PNG 头损坏 + 一堆乱码字符」,扫码工具自然无法识别原始文本。
常见现象包括:二维码能显示,但扫描结果是乱码字符串(如 “测试”)、二维码根本无法识别、浏览器提示“无法加载图像”。
- 立即在
QRcode::png()后加exit或die,强制脚本终止 - 确认生成脚本文件本身是 UTF-8 无 BOM 编码(用 VS Code、Notepad++ 等工具另存为“UTF-8 without BOM”)
- 不要在该脚本中 echo 任何内容、不要 include 其他可能输出的文件、不要开启 output_buffering 且未 clean
endroid/qr-code 中文乱码:字体和编码必须显式指定
6.x 版本默认不带中文字体,也不强制 UTF-8 编码,即使数据传的是中文字符串,底层仍可能按 ISO-8859-1 解析。
关键点在于:encoding 参数只控制 QR 码内容编码方式,不控制字体渲染;而中文显示依赖字体文件是否含对应字形。
立即学习“PHP免费学习笔记(深入)”;
- 必须传
new Encoding('UTF-8'),否则库可能用默认 Latin-1 编码压缩中文,导致解码失败 - 使用
PngWriter时,需手动指定支持中文的字体路径,例如:->writer(new PngWriter(new ImagickImageBackEnd(), new Font(__DIR__.'/simhei.ttf'))) - 推荐字体:Windows 用
simhei.ttf(黑体),Linux 用/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf(需确认含 CJK 字符) - 如果没指定字体,库会 fallback 到内置位图字体,它完全不支持中文
PHP 文件编码、HTTP 响应头、数据源三者必须同为 UTF-8
哪怕字体和编码都设对了,只要其中一环是 GBK 或带 BOM 的 UTF-8,就可能触发双重编码或解析错位。
典型错误链:$_GET['text'] 是 URL 编码过的 UTF-8,但 PHP 文件是 GBK 编码 → urldecode() 后变成乱码字符串 → 再喂给 QR 库 → 最终二维码里存的就是乱码。
- 检查 PHP 文件保存格式:必须是 UTF-8 无 BOM(BOM 会作为不可见字符写入响应体,破坏 PNG 结构)
- 如果从 GET/POST 接收中文,确保接收前没有
mb_convert_encoding()错误转码,也别用iconv('GBK', 'UTF-8', ...)这类假设性转换 - 不需要手动设置
header('Content-Type: image/png; charset=utf-8')—— PNG 是二进制格式,charset参数无效,反而可能引发兼容问题
用 phpqrcode 时最常漏掉的两件事
这个老牌库轻量但隐性约束多,很多开发者照着示例复制粘贴后就出问题,核心卡点就两个。
-
QRcode::png()第二个参数为false时,表示输出到浏览器,此时必须保证该 PHP 文件**只做这一件事**,不能混用 MVC 框架的模板输出逻辑 - 若要支持中文,必须修改
phpqrcode.php源码里的QRencode::encode()方法,在调用pack()前对输入字符串执行mb_convert_encoding($string, 'UTF-8', 'auto'),否则 GBK 环境下直接崩 - 不建议在生产环境用
phpqrcode处理用户输入的中文,它对多字节字符处理过于脆弱;优先换成endroid/qr-code或bacon/bacon-qr-code



















