Laravel + JSでバーコードを読み取る(ダウンロード可)

さてさて、以前このブログで、Python, PHP, JavaScriptでQRコードをつくってみよう!という記事をお届けしました。

そして、QRコードといわれて思い出すもう一つの読み取り形式があります。
そうです、バーコードです。

買い物をするほほぼどんな商品にもバーコードが付けられていますし、また配送業者さんがバーコードをピッ!と読み取って配送完了処理をしていたりいますね。

そこで、今回はウェブ環境だけでこのバーコードを読み取り、配送完了チェックするシンプルな機能をつくってみることにしました。

ぜひ参考になれば幸いです!

※ 開発環境: Laravel 5.7

配送情報をつくる

まずは配送データを管理するテーブルshipmentsをつくります。
以下のコマンドでモデルと一緒に2つ同時で作成しましょう。

php artisan make:model Shipment -m

では、マイグレーションを開いて以下のように商品ID(バーコードのID)と商品名、配送先、そして配送の状況がわかるstatusフィールドを追加します。

Schema::create('shipments', function (Blueprint $table) {
    $table->increments('id');
    $table->string('product_code');
    $table->string('product_name');
    $table->string('address');
    $table->string('status');
    $table->timestamps();
});

そして、テストデータをこのテーブルに追加するSeederもつくっておきます。

php artisan make:seed ShipmentsTableSeeder

中身はこのようにします。

public function run()
{
    $shipping_products = [
        '9784167908782' => 'Jimmy',
        '9784800270665' => 'スマホを落としただけなのに',
        '9784334768805' => '舟を編む'
    ];
    foreach ($shipping_products as $product_code => $product_name) {

        $shipment = new \App\Shipment();
        $shipment->product_code = $product_code;
        $shipment->product_name = $product_name;
        $shipment->address = '東京都墨田区押上1丁目1−2';
        $shipment->status = 'shipping'; // 配送中
        $shipment->save();

    }
}

※ ちなみに配送商品は私が最近読んだ(読みかけ)の小説で、住所は東京スカイツリーのものになっています。またstatusshipping(配送中)としています。

では、Seederを同じフォルダにあるDatabaseSeederに登録してマイグレーションを実行しましょう。

public function run()
{
    $this->call(ShipmentsTableSeeder::class);
}
php artisan migrate:fresh --seed

作成されたデータはこうなります。

バーコードの読み取り部分をつくる

では続いてバーコードのよみとり部分をJavaScriptで作っていきましょう。

利用するパッケージはquaggaJSです。(2018年11月8日現在、MITライセンスで配布されています。商用にも利用しやすいでしょう。

では実際のコードです。

まずはHTMLから。
QuaggaJSでは初期状態でセレクターが#interactive.viewportとなっている場所でカメラの映像が表示されますので、これを追加します。

<div id="interactive" class="viewport"></div>

そして、メインのJavaScriptコードです。

<script src="./js/quaggaJS/dist/quagga.js"></script>
<script>

    Quagga.init({
        inputStream: { type : 'LiveStream' },
        decoder: {
            readers: [{
                format: 'ean_reader',
                config: {}
            }]
        }
    }, (err) => {

        if(!err) {

            Quagga.start();

        }

    });

    Quagga.onDetected((result) => {

        var code = result.codeResult.code;
        // ここでAjaxを通して配送完了処理をする

    });

</script>

今回はよりシンプルにしたかったので、バーコード検知中のデバッグ情報(緑の枠線やバーコードを検知した時に表示される赤い線)は省略しています。

もしこれらを追加したい場合は、<canvas>タグのcssを設定し、Quagga.onProcessed()内で、キャンバスの枠線を引くコードが必要になってきます。詳しくは、QuaggaJS付随のテストコードlive_w_locator.htmlを参考にするといいでしょう。

では、コードの説明です。

まずQuagga.init()です。
第1引数で各種設定をすることができます。
ちなみに、ean_readerというのはJANコード形式のバーコードに対応するタイプです。

そして、Quagga.onDetected()です。
その名の通りバーコードが検出されたときに呼ばれる関数で、この中でAjaxを通して配送完了処理をすることになります。

Ajaxで配送完了処理をする

では、バーコードが検出されたらstatusを完了を意味するshippedへ変更するコードを書いていきましょう。

まずは先ほどに続いてJavaScriptのコードから。
Ajax通信が簡単にできるaxioscdnから読み込みます。

<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
let checking = false;

Quagga.onDetected((result) => {

    var code = result.codeResult.code;
    const url = '/shipment/check';

    if(!checking) {

        checking = true;
        axios.post(url, { code: code })
            .then((response) => {

                const result = response.data.result;

                if(result) {

                    const productName = response.data.shipment.product_name;
                    alert('「'+ productName +'」の配送が完了しました。');

                } else {

                    alert('この商品は登録されていません。');

                }

            })
            .catch((error) => {})
            .then(() => {

                checking = false;

            });

    }

});

まずcheckingですが、これはAjax通信で配送完了処理をしている間もバーコード読み取りは実行中なので、何度も何度も後から実行されてしまうことになります。これではユーザービリティがいいとは言えません。そのため、Ajax通信をしている間は新しい処理をスキップするようにしています。

そして、もし配送処理が完了したら商品名をアラート表示し、もし登録されていない場合はエラー表示します。

では、続いてAjaxでデータ送信される先のLaravel側を見てみましょう。

public function check(Request $request) {

    $query = \App\Shipment::where('product_code', $request->code);

    if($query->exists()) {

        $shipment = $query->first();
        $shipment->status = 'shipped';
        $shipment->save();

        return [
            'result' => true,
            'shipment' => $shipment
        ];

    }

    return ['result' => false];

}

まずproduct_codeを使ってこのバーコードの配送データが存在しているかどうかをチェックしています。

また、データが見つかればstatusshipped(配送完了)に変更して保存しています。

テストしてみる

では、実際にスマホを使ってテストしてみましょう。

まずは、配送データに登録されている商品をバーコード・スキャンしてみます。

配送完了のアラートが表示されました。
念の為、DBテーブルも見てみましょう。

こちらもうまくshippedへ変更になっています。

では、次に登録されていない商品をスキャンしてみましょう。

こちらもうまく処理ができています。

お疲れ様でした!

ちなみに

Google Chromeの場合は必ずセキュア(つまり、HTTPS)でアクセスしているページでないとカメラが使えないようになっています。そのため、ローカルでテストするには、自分で署名した証明書を使ってHTTPS接続するか、もしくはFirefoxはまだHTTPでもカメラ対応しているのでこちらを使うといいでしょう。

教材ソースコードをダウンロードする

今回実際に開発したソースコード一式をダウンロードすることができます。

※ ただし、QuaggaJS本体はご自身で設置してください。

Laravel + JSでバーコード配送チェック