【PHP】endroid/qr-codeを使ってQRコード画像を出力してみた話

# はじめに
タイトルの通りですが、
endroid/qr-codeを使ってQRコード画像を出力してみました。

以下で作成した環境を引き続き利用していますので、
今回もコマンドラインから実行となります。

* [【PHP】TCPDF + FPDIでPDFを出力してみた話](https://qiita.com/suupoo/items/0eb0f42c70bf535a66c3)

# 本編
## 環境構築
[【PHP】TCPDF + FPDIでPDFを出力してみた話 > Docker](https://qiita.com/suupoo/items/0eb0f42c70bf535a66c3#docker)を元に
今回新たに必要となった、**gd拡張モジュール**の導入設定を追加します。

```dockerfile
# GD
RUN apt-get install -y libjpeg-dev libpng-dev libfreetype6-dev
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ && \
    docker-php-ext-install gd
```

追加後、再度ビルドします。

```terminal
# docker-compose build --no-cache
```

## Composer
Composerを使って、"endroid/qr-code"をインストールしていきましょう。

```terminal
# cd /home/work/src/
# composer require endroid/qr-code
Using version ^3.9 for endroid/qr-code
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 15 installs, 0 updates, 0 removals
  - Installing myclabs/php-enum (1.7.6): Downloading (100%)         
  - Installing symfony/polyfill-ctype (v1.18.1): Downloading (100%)         
  - Installing symfony/polyfill-php80 (v1.18.1): Downloading (100%)         
  - Installing symfony/polyfill-mbstring (v1.18.1): Downloading (100%)         
  - Installing symfony/polyfill-intl-normalizer (v1.18.1): Downloading (100%)         
  - Installing symfony/polyfill-intl-grapheme (v1.18.1): Downloading (100%)         
  - Installing symfony/string (v5.1.5): Downloading (100%)         
  - Installing symfony/property-info (v5.1.5): Downloading (100%)         
  - Installing symfony/property-access (v5.1.5): Downloading (100%)         
  - Installing symfony/deprecation-contracts (v2.2.0): Downloading (100%)         
  - Installing symfony/options-resolver (v5.1.5): Downloading (100%)         
  - Installing khanamiryan/qrcode-detector-decoder (1.0.3): Downloading (100%)         
  - Installing dasprid/enum (1.0.2): Downloading (100%)         
  - Installing bacon/bacon-qr-code (2.0.2): Downloading (100%)         
  - Installing endroid/qr-code (3.9.1): Downloading (100%)         
symfony/polyfill-intl-normalizer suggests installing ext-intl (For best performance)
symfony/polyfill-intl-grapheme suggests installing ext-intl (For best performance)
symfony/property-info suggests installing psr/cache-implementation (To cache results)
symfony/property-info suggests installing symfony/doctrine-bridge (To use Doctrine metadata)
symfony/property-info suggests installing phpdocumentor/reflection-docblock (To use the PHPDoc)
symfony/property-info suggests installing symfony/serializer (To use Serializer metadata)
symfony/property-access suggests installing psr/cache-implementation (To cache access methods.)
bacon/bacon-qr-code suggests installing ext-imagick (to generate QR code images)
endroid/qr-code suggests installing roave/security-advisories (Avoids installation of package versions with vulnerabilities)
endroid/qr-code suggests installing symfony/security-checker (Checks your composer.lock for vulnerabilities)
endroid/qr-code suggests installing setasign/fpdf (Required to use the FPDF writer.)
Writing lock file
Generating autoload files
12 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
```
## 実装
”Google.com”へのリンクをQRコードにしてみます。

### ファイル構成
```terminal
# cd /home/work/

# ls /home/work/output/img/qr/qrYYYYmmdd-HHiiss #PDF出力ファイル
# ls /home/work/src/resources/img/png/qr-logo.png #QRコード中心に表示されるロゴマーク
# ls /home/work/bin/make-qr.php #コマンドラインで実行するソース
# ls /home/work/src/classes/MyQrCode.php # TCPDF利用クラス
# ls /home/work/src/classes/QrCode/FontColorWithAlpha.php.php # フォントカラークラス(割愛)
```

### ソース

```php:/home/work/bin/make-qr.php
<?php

require_once __DIR__ . '/../src/bootstrap.php';

use Classes\MyQrCode;
use Classes\QrCode\FontColorWithAlpha;

// QRコードの画像ファイルを出力
$myQrCode = new MyQrCode('https://www.google.com/');
$myQrCode->setForegroundColor(new FontColorWithAlpha(255, 0, 0));
$myQrCode->setBackgroundColor(new FontColorWithAlpha(255, 255, 0));
$myQrCode->outputQrCodeFile();
```

```php:/home/work/src/classes/MyQrCode.php
<?php

namespace Classes;

use Endroid\QrCode\LabelAlignment;
use Endroid\QrCode\QrCode;
use Classes\QrCode\FontColorWithAlpha;

class MyQrCode
{
    //デフォルト設定
    private $size = 300;//QRコードサイズ
    private $margin = 10;//余白

    //バーコードの色(デフォルト:黒)
    private $foregroundColor = [
        'r' => 0,
        'g' => 0,
        'b' => 0,
        'a' => 0
    ];
    //背景色(デフォルト:白)

    private $backgroundColor = [
        'r' => 255,
        'g' => 255,
        'b' => 255,
        'a' => 0
    ];

    // 文字エンコーディング
    const ENCODING = 'utf-8';

    // ラベル
    const LABEL_TEXT = 'QRコードを読み込む';
    const LABEL_FONT_SIZE = 15;

    // // 出力ファイル
    const OUTPUT_FILE_DIR = __DIR__.'/../../output/img/qr/';
    const OUTPUT_FILE_NAME = 'qr';

    // ロゴ
    const LOGO_IMG = __DIR__.'/../resources/img/png/qr-logo.png';
    const LOGO_SIZE_WIDTH = 50; //幅
    const LOGO_SIZE_HEIGHT = 50;//高さ

    // フォントファイル
    const FONT_FILE_NAME = __DIR__.'/../resources/font/ipam.ttf';

    /**
     * コンストラクタ
     */
    public function __construct(string $_text)
    {
        $this->qrCode = new QrCode($_text);
    }

    /**
     * QRCodeの画像出力前の準備処理
     */
    private function prepareOutput()
    {
        // 可変パラメータ
        $this->qrCode->setSize($this->size); // QRコードのサイズ
        $this->qrCode->setMargin($this->margin); //QRコードと画像の余白
        $this->qrCode->setForegroundColor($this->foregroundColor);//QRコードの色
        $this->qrCode->setBackgroundColor($this->backgroundColor);//背景色
        // 固定パラメータ
        $this->qrCode->setEncoding(self::ENCODING);//文字エンコード
        //QRコードの下に表示されるラベル
        $this->qrCode->setLabel(
            self::LABEL_TEXT,
            self::LABEL_FONT_SIZE,
            self::FONT_FILE_NAME,
            LabelAlignment::CENTER()
        );
        //QRコードの中央に表示されるロゴ
        //ロゴのファイル
        $this->qrCode->setLogoPath(self::LOGO_IMG);
        //ロゴのサイズ
        $this->qrCode->setLogoSize(self::LOGO_SIZE_WIDTH, self::LOGO_SIZE_HEIGHT);
    }

    /**
     * QRCodeの画像出力
     */
    public function outputQrCodeFile()
    {
        // 出力準備
        $this->prepareOutput();
        // ファイル出力
        $this->qrCode->writeFile($this->getOutputFilename());
    }

    /**
     * 出力するファイル名を取得する
     * @return string ファイル名
     */
    private function getOutputFilename()
    {
        return self::OUTPUT_FILE_DIR . self::OUTPUT_FILE_NAME . date("Ymd-His"). '.png';
    }

    /**
     *
     * QRコードの色を設定する
     * @param $_fontColor 文字色クラス
     */
    public function setForegroundColor(FontColorWithAlpha $_fontColor)
    {
        $this->foregroundColor = $_fontColor->toArray();
    }

    /**
     *
     * 背景色の色を設定する
     * @param $_fontColor 文字色クラス
     */
    public function setBackgroundColor(FontColorWithAlpha $_fontColor)
    {
        $this->backgroundColor = $_fontColor->toArray();
    }

    /**
     *
     * QRコードのサイズを設定する
     * @param $_fontColor 文字色クラス
     */
    public function setSize(int $_size)
    {
        $this->size = $_size;
    }

    /**
     *
     * QRコードの余白を設定する
     * @param $_fontColor 文字色クラス
     */
    public function setMargin(int $_margin)
    {
        $this->margin = $_margin;
    }
}
```

### 実行コマンド
```terminal
php /home/work/bin/make-qr.php
```

## 実行結果
以下のようにファイルが出力されます。
![qr20200927-154038.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338551/e5931fdd-b80a-665d-dd76-962fcfe28f34.png)

# 終わりに
QRコードを作成してくれるサービスは既にいくつもあるかと思いますが、
大量に必要な場合や動的に作成したい場合は、簡単に自前で用意できそうですね。

# 参考
1. [GitHub - endroid/qr-code](https://github.com/endroid/qr-code)
2. [Qiita -【PHP】endroid/qr-codeを使ってQRコードを生成してみる] (https://qiita.com/danishi/items/fd8038ee373c04b94bf6)