应弃用已归档的2amigos/yii2-qrcode-helper,直接使用endroid/qr-code v5:通过pngwriter生成png二维码,在控制器中设置response::format_raw与content-type头,视图中以/img src="/site/qr?text=xxx"/方式引用,传入utf-8字符串并可选setencoding('utf-8'),避免高容错级导致中文溢出失败。

composer install 失败:找不到 2amigos/yii2-qrcode-helper
这个包在 Packagist 上已归档,composer require 2amigos/yii2-qrcode-helper 会报 Could not find package 2amigos/yii2-qrcode-helper。它依赖的底层库 endroid/qr-code 已升级到 v4+,而该 Yii2 扩展只适配到 v3.x,官方不再维护。
实际做法是绕过这个扩展,直接用现代版 endroid/qr-code(v4 或 v5)配合 Yii2 手动封装——更轻、更可控、无兼容风险。
用 endroid/qr-code v5 生成二维码图片(PNG)
这是目前最稳的路径:不走 Yii2 组件注册,不改配置文件,直接在控制器或视图里调用。v5 默认支持 PHP 8.0+,输出 PNG/JPEG/SVG,无需 GD 扩展(用 imagick 或纯 PHP 实现)。
-
composer require endroid/qr-code(v5.x,别加@dev) - 生成时指定尺寸和边距:
size是内容区域宽高(不含 margin),margin是白边像素值 - 注意
WriterInterface::WRITE_STRING返回的是原始 PNG 二进制,不能直接 echo,要用header()配合echo $result
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Writer\PngWriter;
$qrCode = QrCode::create('https://example.com')
->setSize(300)
->setMargin(10);
$writer = new PngWriter();
$result = $writer->write($qrCode);
header('Content-Type: image/png');
echo $result->getString();
在 Yii2 视图中安全嵌入二维码(非 base64)
别把二维码二进制塞进 <img src="data:image/png;base64,..."> —— 它会让 HTML 体积暴增,无法缓存,且某些邮件客户端/微信内核会拒绝渲染。
正确方式是提供一个独立 action,返回纯图片流,然后视图里用标准 <img src="/site/qr?text=xxx"> 引用。
- action 内必须设置
Yii::$app->response->format = \yii\web\Response::FORMAT_RAW - 务必调用
Yii::$app->response->headers->add('Content-Type', 'image/png'),否则浏览器当文本下载 - URL 参数需过滤:用
htmlspecialchars(urlencode($text))防注入,但注意urlencode已足够,不用再 htmlspecialchars
中文内容乱码或报错 “Error while generating QR code”
不是字体问题,是 endroid/qr-code v4+ 默认不处理 UTF-8 文本编码——它只校验是否为合法字符串,但 QR 标准要求中文必须用 UTF-8 编码后转为字节流,而默认 writer 不自动做这步。
解决方法只有两个:
- 确保传入
QrCode::create()的字符串已经是 UTF-8 编码(Yii2 默认就是,除非你从 GBK 表单手动读取没转码) - 如果仍报错,显式指定编码器:
->setEncoding(new Encoding('UTF-8'))(需use Endroid\QrCode\Encoding\Encoding;)
常见坑:用 mb_convert_encoding($str, 'UTF-8', 'GBK') 转码后没检查返回值是否 false;或者在 Windows 环境下读取本地文件时忘了加 file_get_contents($path, false, null, 0, -1, ['encoding' => 'UTF-8'])。
复杂点在于:二维码容错等级(setErrorCorrectionLevel())设得太高(如 ErrorCorrectionLevel::HIGH)时,中文字符多会导致数据块溢出,反而生成失败——这时要降级到 MEDIUM 或缩短内容。











