编程

Laravel 10 中如何生成二维码

1158 2023-05-29 09:22:00

本文中,我们将探讨如何在 Laravel 中生成二维码。

首先,我们需要引入 Laravel 的第三方支持包 simple-qrcode。这个包封装了 Bacon/BaconQrCode 包,它本身是 ZXing 库的一个端口,但适用于 PHP.

你也可以直接和 BaconQrCode 包进行交互,而无需通过 simple-qrcode。不过在使用 Laravel 时 simple-qrcode 提供了更好的开发体验。此外,开箱即用支持在二维码上叠加图像。

第一步:安装

预备一个新的 Laravel 项目。

$ laravel new qrcodegenerator

设置数据库连接。然后通过 Composer 安装 simple-qrcode 包。

$ composer require simplesoftwareio/simple-qrcode "~4"

可选的!如果你想以 .png 格式创建二维码。你需要安装 imagick 扩展。大部分情况下,你只需要使用 pecl install imagick 通过  pecl 安装。如果对你无效的话,请自行搜索如何安装。

第二步:创建控制器

我们需要先将控制器和路由接通。

创建新控制器 QrCodeController.

$ php artisan make:controller QrCodeController

然后在 routes/web.php` 路由文件中设置:

<?php

use App\Http\Controllers\QrCodeController;
use Illuminate\Support\Facades\Route;

Route::get('/', [QrCodeController::class, 'show']);

此时浏览器中打开 URL,会出现一个空白页面。

第三步:生成二维码

最基础的,你可以调用 QrCode facade 带上 generate 来生成你要渲染的内容。然后你就能得到一个二维码。

我的 QrCodeController 中,我创建了一个使用默认设置的二维码,并包含如下内容 "Hello, World!"。

<?php

namespace App\Http\Controllers;

use SimpleSoftwareIO\QrCode\Facades\QrCode;

class QrCodeController extends Controller
{
    public function show()
    {
        return QrCode::generate(
            'Hello, World!',
        );
    }
}

刷新页面,然后就生成了二维码…

第 4 步:自定义生成二维码

好吧,那再来点有趣的怎么样?一点颜色?让我们使用几种方法来更改背景颜色、前景颜色和边距。

public function show()
{
    return QrCode::size(200)
        ->backgroundColor(255, 255, 0)
        ->color(0, 0, 255)
        ->margin(1)
        ->generate(
            'Hello, World!',
        );
}

结果如下:

让我们尝试一些能让我们的二维码脱颖而出的东西。我不再谈论颜色了。

我们实际上可以修改二维码的样式和眼睛(三个角)。试试这个:

return QrCode::size(200)
        ->style('dot')
        ->eye('circle')
        ->color(0, 0, 255)
        ->margin(1)
        ->generate(
            'Hello, World!',
        );

结果:

在结束本节之前。还有一个关于颜色的:渐变。

$from = [255, 0, 0];
$to = [0, 0, 255];

return QrCode::size(200)
    ->style('dot')
    ->eye('circle')
    ->gradient($from[0], $from[1], $from[2], $to[0], $to[1], $to[2], 'diagonal')
    ->margin(1)
    ->generate(
        'Hello, World!',
    );

通过指定起始和终止颜色,以及渐变类型(垂直、水平等)。你可以创造一些非常酷的东西!

合并图片

要在二维码中叠加图像,我们需要改变一些事情的处理方式。

为了做好准备,我在 storage/app 文件夹中放了一张图片(twitter.jpg)。然后,通过调用 ->merge($filepath),simple-qrcode 将加载该图像并将其覆盖到二维码上。

如果您想自己提取图像数据,可以用 mergeString 代替 merge。例如:->mergeString(Storage::get($path))

只有 png 二维码才支持合并图像,所以我们也需要在上面指定格式。

public function show()
    {
        $data = QrCode::size(512)
            ->format('png')
            ->merge('/storage/app/twitter.jpg')
            ->errorCorrection('M')
            ->generate(
                'https://twitter.com/HarryKir',
            );

        return response($data)
            ->header('Content-type', 'image/png');
    }

结果如下:

你可能已经注意到关于 errorCorrection 的行。当我们覆盖图像时,二维码的部分数据会变得模糊不清。

默认情况下,errorCorrection 设置为最低值 ('L')。如果你试图这样扫描你的二维码,有可能二维码不会扫描成功。为了解决这个问题,我们将 errorCorrection 级别上调一个级别,直到我们的二维码可以扫描。

级别包括:

  • L: Low (7% correction)
  • M: Medium (15% correction)
  • Q: Quartile (25% correction)
  • H: High (30% correction)

校正级别越高,二维码就变得越“嘈杂。为了保持外观,最好在可扫描的二维码旁边加上最低的校正级别。

下载生成的二维码

要返回下载响应,你可以将二维码存为文件,并使用 return response()->download($path) 返回其路径;或者流式输出二维码内容,而步使用文件系统。

使用 streamDownload 的示例:

public function download()
{
    return response()->streamDownload(
        function () {
            echo QrCode::size(200)
                ->format('png')
                ->generate('https://harrk.dev');
        },
        'qr-code.png',
        [
            'Content-Type' => 'image/png',
        ]
    );
}

在 Blade 中生成二维码

由于我们一直在使用 Facade,因此在 Blade 中生成二维码只需重复上述步骤即可。调用 facade,根据需要进行自定义,然后调用 generate

{!! QrCode::size(256)->generate('https://google.com') !!}

或者另一种方法,手动对图像标签中的数据进行编码。例如,如果出于任何原因需要更改图像类型。

<img src="data:image/png;base64, {!! base64_encode(QrCode::format('png')->size(256)->generate('https://google.com')) !!} ">

二维码数据类型

好吧,所以我们在这些例子中使用了 URL。移动设备足够聪明,可以在扫描时找到如何处理这些问题,但我们可以更进一步。

总结一下:simple-qrcode 有几个 helpers 来指定二维码将包含的数据。你可以将 generate 方法替换为以下任何方法。

下面是一些例子:

Email

打开一封空白电子邮件,收件人为 “hello@example.com"。

QrCode::size(200)->email('hello@example.com');

打开一封具有预定义主题和正文的电子邮件。

QrCode::size(200)->email('hello@example.com', 'Hello World', 'This is a test message.');

电话号码

QrCode::size(200)->phoneNumber('555-555-5555');

短信

向 555-555-5555 发送一条短信,并附上一条预先写好的信息 “Hi!”。

QrCode::size(200)->SMS('555-555-5555', 'Hi!');

Wi-Fi

分享 WiFi 凭据给访客。

QrCode::size(200)->wiFi([
    'encryption' => 'WPA/WEP',
    'ssid' => 'SSID of the network',
    'password' => 'Password of the network',
    'hidden' => 'Whether the network is a hidden SSID or not.'
]);

地理位置

通过提供纬度和经度来共享位置。

QrCode::size(200)->geo(51.378638, -0.100897);

结语

要了解更多高级自定义选项,请查看 simple-qrcode 的文档。