Composer require 找不到包时,先确认包名正确、源为 Packagist 官方源,再根据 PHP 版本选择 endroid/qr-code v4+(PHP 8.0+)或 v3.5(PHP 7.4),避免使用已废弃的 simplesoftwareio/simple-qrcode。

composer require 时提示找不到包?确认包名和仓库源
Composer 安装 QR Code 库最常卡在第一步:根本搜不到可用包。主流 PHP 二维码库是 endroid/qr-code(v4+ 支持 PHP 8.0+)和更轻量的 bacon/bacon-qr-code(纯函数式,无依赖)。别用过时的 simplesoftwareio/simple-qrcode——它已停止维护,且 Laravel 10+ 兼容性差。
执行前先检查 Composer 是否启用 Packagist 官方源:
composer config -g repo.packagist.org composer https://packagist.org
然后运行(以 endroid/qr-code 为例):
composer require endroid/qr-code
- 如果报
Could not find package endroid/qr-code,大概率是公司内网镜像没同步最新包,临时切回官方源:composer config -g repo.packagist.org composer https://packagist.org - 若项目锁定了 PHP 版本(如
"php": "^7.4"),而 v4.x 要求 PHP 8.0+,就降级安装 v3.5:composer require endroid/qr-code:^3.5 - 不推荐用
--dev安装——生成二维码通常是运行时功能,不是开发工具
生成 PNG 二维码但浏览器显示损坏图片?检查响应头和输出缓冲
用 endroid/qr-code 生成后直接 echo 或 return 图片二进制流,却看到“破损的图像”图标,90% 是响应头缺失或输出被截断。
正确做法是显式设置 Content-Type 并确保无额外输出:
$qrCode = (new QrCode('https://example.com'))
->setSize(300)
->setMargin(10);
header('Content-Type: image/png');
echo $qrCode->writeString();
- 必须在
echo前调用header(),且不能有任何空格、BOM 或var_dump()留下的输出 - 如果框架(如 Laravel)已启动响应对象,别手动
header(),改用响应类:return response($qrCode->writeString())->header('Content-Type', 'image/png'); -
writeString()返回 raw PNG 数据;writeFile()写入磁盘,适合缓存场景
怎么给二维码加 logo?注意尺寸比例和格式兼容性
endroid/qr-code v4+ 原生支持 logo 叠加,但极易因尺寸失控导致扫码失败。
关键参数只有两个:setLogoPath() 和 setLogoSize():
$qrCode = (new QrCode('https://example.com'))
->setSize(300)
->setMargin(10)
->setLogoPath('/path/to/logo.png')
->setLogoSize(60); // logo 宽高均为 60px
- logo 尺寸建议 ≤ 25% 的二维码边长(即 300px 二维码,logo 不超过 75px),否则中心模块被遮盖,主流扫码器无法识别
- logo 必须是 PNG 且带透明背景;JPG 会覆盖底色,导致对比度不足
- v3.x 使用
setValidateResult(false)关闭校验才能加 logo,v4+ 默认允许,但校验仍建议开启(setValidateResult(true))来提前发现不可扫问题
Laravel 中快速返回二维码响应?避免中间件干扰输出
Laravel 路由中直接返回二维码,常被全局中间件(如 `VerifyCsrfToken` 或日志中间件)意外注入 HTML 或换行,导致图片损坏。
最稳方案是定义一个不走中间件的路由,并用原生响应:
// routes/web.php
Route::get('/qrcode/{text}', function ($text) {
$qrCode = (new QrCode(urldecode($text)))
->setSize(250)
->setMargin(5);
return response($qrCode->writeString())
->header('Content-Type', 'image/png')
->header('Cache-Control', 'public, max-age=31536000');
});
- 加
Cache-Control头让 CDN 或浏览器缓存一年,减少重复生成开销 - 不要在控制器里用
view()渲染——模板引擎可能自动添加空白符 - 如果必须走中间件,确保中间件末尾没有
dd()、Log::info()或任何 echo/print 输出
复杂点在于 logo 叠加后的容错率下降,哪怕只多压 5px,微信扫码就可能失败;建议生成后用手机实测,别只看浏览器预览。










