PHPフレームワーク「Laravel」とActiveReportsJSで帳票を出力する

先日公開した記事では、PHPのWebアプリケーションフレームワーク「Laravel」でWeb APIを作成する方法、及びフロントエンドでVue.jsとWijmoを使う方法をご紹介しました。

今回はJavaScript帳票ライブラリ「ActiveReportsJS(アクティブレポートJS)」を使用して、LaravelのWebアプリケーションから帳票を出力する方法をご紹介したいと思います。

Laravelアプリケーションの作成

以下のコマンドをターミナルなどから実行してLaravelのアプリケーションを作成します。Laravelの導入方法は以前公開した記事で解説しています。

composer create-project laravel/laravel laravel-reporting --prefer-dist

作成が完了したら、プロジェクトのフォルダ配下に移動します。

cd laravel-reporting

データベースの作成

データベースの設定

データベースの設定の作業に入る前に、「config/app.php」を以下のように修正し、あらかじめ関連するタイムゾーンやロケールなどを日本のものに修正しておきます。

・・・
(中略)
・・・
'timezone' => 'Asia/Tokyo',
・・・
(中略)
・・・
'locale' => 'ja',

今回はデータベースにSQLiteを使用するので、「.env」ファイルのDB_CONNECTIONを「sqlite」に変更します。また、元々あったMySQLの接続設定は削除するかコメントアウトしておきます。

DB_CONNECTION=sqlite
#DB_HOST=127.0.0.1
#DB_PORT=3306
#DB_DATABASE=laravel
#DB_USERNAME=root
#DB_PASSWORD=

また、「database」フォルダ配下に空の「database.sqlite」ファイルを作成します。

Laravelでは「Migration」という機能を使用して、データベースの作成や管理が可能です。以下のコマンドを実行してモデルを作成します。allオプション(-a)を追加することで、コントローラーやマイグレーションにモデルが紐づくようにします。ファイル名は「Invoice」とします。

php artisan make:model -a Invoice

上記のコマンドを実行すると、「database/migrations」フォルダ配下にマイグレーションファイルが作成されるので、upメソッド内に請求書の作成に必要なカラムを追加します。

public function up()
{
    Schema::create('invoices', function (Blueprint $table) {
        $table->id();
        $table->string('billno');
        $table->string('slipno');
        $table->string('customerid');
        $table->string('customername');
        $table->string('products');
        $table->integer('number');
        $table->integer('unitprice');
        $table->datetime('date');                    
        $table->timestamps();
    });
}

以下のコマンドを実行してマイグレーションを実行します。

php artisan migrate

完了すると「Migration table created successfully.」のメッセージが表示されます。

テストデータの作成

次に「Seeder」という機能を利用して、データベースにデータを挿入します。「seeders」フォルダの「InvoiceSeeder.php」ファイルを編集します。今回追加したいInvoiceモデルをインポートしてrunメソッドを修正します。

<?php

namespace Database\Seeders;

use App\Models\Invoice;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class InvoiceSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table("Invoices")->insert(
            [
                [
                    'billno' => 'WS-DF502',
                    'slipno' => 'GB465',
                    'customerid' => 1,
                    'customername' => '長崎カントリーフーズ',
                    'products' => 'コーヒー 250 ml',
                    'number' => 100,
                    'unitprice' => 100,
                    'date' => '2021-01-05T00:00:00',
                    'created_at' => now(),
                    'updated_at' => now()
                ],
                [
                    'billno' => 'WS-DF502',
                    'slipno' => 'GB465',
                    'customerid' => 1,
                    'customername' => '長崎カントリーフーズ',
                    'products' => '紅茶 350 ml',
                    'number' => 300,
                    'unitprice' => 120,
                    'date' => '2021-01-05T00:00:00',
                    'created_at' => now(),
                    'updated_at' => now()
                ],
                [
                    'billno' => 'WS-DF502',
                    'slipno' => 'DK055',
                    'customerid' => 1,
                    'customername' => '長崎カントリーフーズ',
                    'products' => '炭酸飲料 (オレンジ) 350 ml',
                    'number' => 200,
                    'unitprice' => 120,
                    'date' => '2021-01-09T00:00:00',
                    'created_at' => now(),
                    'updated_at' => now()
                ],
            ]
        );
    }
}

次に、「DatabaseSeeder.php」ファイルのrunメソッドを修正し、先ほど設定したInvoiceSeederが実行されるようにします。

public function run()
{
    $this->call(InvoiceSeeder::class);
}

以下のコマンドでSeederを実行してダミーデータを登録します。

php artisan db:seed

完了すると「Database seeding completed successfully.」のメッセージが表示されます。

あとは「tinker」を使用して、登録データの確認を行います。以下のコマンドを実行してtinkerを起動します。

php artisan tinker

tinkerのコンソールが起動したら、以下を入力します。データベースに登録したデータが一覧で表示されます。

App\Models\Invoice::all()
Seederで登録したデータの確認
Seederで登録したデータの確認

Web APIの作成

データベースの設定が完了したら、次はWeb APIを作成していきます。今回はデータの参照のみ行うので、Invoiceモデルに紐づいたControllerファイル「app/Http/Controllers/InvoiceController.php」を以下のように記述し、一覧取得(index)の処理を設定します。

・・・
(中略)
・・・
// 一覧取得(index)
public function index()
{
    return Invoice::all();
}

また、今回SQLiteから取り出したデータはテキストとして扱われるため、きちんと数値として取り出されるよう、「app/Models/Invoice.php」にキャストの設定を追加します。

・・・
(中略)
・・・
class Invoice extends Model
{
    use HasFactory;

    protected $casts = [
        'unitprice' => 'integer',
        'number' => 'integer'
    ];
}

次に「/invoices」にアクセスされた時にこのControllerが設定されるようにルーティングの設定を行います。「routes/api.php」ファイルを以下のように設定します。

Route::apiResource('invoices','InvoiceController');

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

Laravel8からcontrollerのNamespaceを設定する必要があるので、設定を変更します。「App/Providers/RouteServiceProvider.php」の29行目のコメントアウトを解除します。

//コメントアウトを解除
protected $namespace = 'App\\Http\\Controllers';

以上でWeb APIの設定は完了です。

Web APIの実行

あとは実際にWeb APIを実行して動作を確認します。以下のコマンドを実行し、APIを起動します。

php artisan serve

APIを起動したら、Postmanなどのツールを使用してリクエストを送信し、テストしてみます。

GET(参照)

「http://127.0.0.1:8000/api/invoices」に対してGETリクエストを実行します。Seederで登録した3件のデータが取得されます。

レポートファイルの作成

次にActiveReportsJSで出力する帳票のレイアウト情報などを含んだレポートファイルを作成します。今回は以下のGitHubで公開しているものを改修して使用します。

なお、レポートファイルの編集にはActiveReportsJSのデザイナのインストールが必要です。無償で使えるトライアル版もございますので、是非お試しください。

GitHubからダウンロードしたファイルから、「reports/Invoice_green_ipa.rdlx-json」をデザイナで開くと、以下のようなレイアウトのレポートファイルが表示されます。

GitHubから取得したサンプルレポートファイル

データソースの作成

ダウンロードしたレポートファイルはテスト用の埋め込みのJSONデータを使用しているので、新しくデータソースを追加します。以下のようにデザイナ右側の[データ]タブからデータソースの削除と追加を行います。
※ この操作を行う前に、前半で作成したLaravelのWeb APIを起動しておいてください。

[データソースの編集]のダイアログが開くので、[データプロバイダ]に「Remote JSON」を選択し、[エンドポイント]に以下のURLを設定し、[変更を保存]をクリックします。

http://127.0.0.1:8000/api/invoices
Web APIのエンドポイントの設定

データセットの作成

データソースを作成したらデータセットを作成します。デザイナ右側のメニューから作成したデータソースの右側にある[+]アイコンをクリックします。

データセットの追加

[新規データセット]ダイアログで、[JSONパス]に以下の値を設定し、[検証]をクリックすると、データベースフィールドが11件作成されます。

$.*

次に、製品の単価と購入数量から購入金額を計算する計算フィールドを追加します。
[計算フィールド]の右側の[+]アイコンをクリックして計算フィールドを追加したら、フィールド名に「price」、値に以下の式を設定し、[変更を保存]をクリックして、ダイアログを閉じます。

{unitprice * number}

デザイナ上でプレビューの実行

以上でデータソース/データセットの設定は完了です。このレポートファイルはすでにTextBoxなどのレポートコントロールと各フィールドとのバインド設定が完了していますので、このままプレビューが実行可能です。
前半の記事でSQLiteに登録したデータが帳票に表示されるのが確認できます。

作成したレポートファイルはプロジェクトの「resources」フォルダ配下に「reports」フォルダを作成して保存します。
また、出力した帳票をPDF形式で保存したい場合はレポートファイル中で使用しているフォントファイルを埋め込む必要があります。今回のサンプルでは「IPAゴシック」を使用しているので、「fonts」フォルダを作成し、GitHubからダウンロードしたファイル中に含まれているフォントファイルもコピーします。

レポートファイルとフォントファイルをコピー
レポートファイルとフォントファイルをコピー

Viewの作成

レポートファイルの作成が完了したら、仕上げとしてLaravelのViewの部分を作成していきます。LaravelでJavaScriptなどを用いてフロントエンド開発を行う場合、「Laravel Mix」というwebpackをベースとしたビルドツールが使用可能です。

Laravelのプロジェクト作成時に一緒に作成される「package.json」にはデフォルトでLaravel Mixの依存関係が記述されています。

・・・
(中略)
・・・
    "devDependencies": {
        "axios": "^0.21",
        "laravel-mix": "^6.0.6",
        "lodash": "^4.17.19",
        "postcss": "^8.1.14"
    }
}

以下のコマンドを実行し、Laravel Mixを含む依存パッケージをインストールします。

npm install

インストールが完了したら、続いてActiveReportsJSのモジュールもインストールします。

npm install @grapecity/activereports@2.1.3 @grapecity/activereports-localization@2.1.3

次に「webpack.mix.js」を以下のように記述し、静的リソースのビルド設定を行います。

const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
        .js('node_modules/@grapecity/activereports', 'public/js')
        .js('node_modules/@grapecity/activereports-localization', 'public/js')
        .postCss('node_modules/@grapecity/activereports/styles/ar-js-ui.css', 'public/css')
        .postCss('node_modules/@grapecity/activereports/styles/ar-js-viewer.css', 'public/css')
        .copy('resources/reports/Invoice_green_ipa.rdlx-json', 'public/reports') 
        .copy('resources/fonts/ipag.ttf', 'public/fonts'); 

「resources/views/viewer.blade.php」を新たに追加し、ActiveReportsJSのビューワを組み込んだBladeテンプレートを作成します。

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>ActiveReportsJSビューワ</title>

    <link rel="stylesheet" href="{{ asset('/css/ar-js-ui.css') }}" />
    <link rel="stylesheet" href="{{ asset('/css/ar-js-viewer.css') }}" />
    <script type="text/javascript" src="{{ asset('/js/activereports.js') }}"></script>
    <script type="text/javascript" src="{{ asset('/js/activereports-localization.js') }}"></script>
</head>

<body onload="load()">
    <div id="ARJSviewerDiv" style="height: 100vh"></div>
    <script>
        function load() {
            const viewer = new ActiveReports.Viewer('#ARJSviewerDiv', {
                language: 'ja'
            });
            // PDFエクスポートを行う場合はフォントの登録を行う
            var IPAGothic = {
                name: "IPAゴシック",
                source: "./fonts/ipag.ttf"
            };
            GC.ActiveReports.Core.FontStore.registerFonts(IPAGothic);
            viewer.open("{{ asset('/reports/Invoice_green_ipa.rdlx-json') }}");
        }
    </script>
</body>

</html>

「http://127.0.0.1:8000/viewer」にアクセスしたときに先ほどのBladeテンプレートの内容が表示されるよう、「routes/web.php」にルーティングの設定を追加します。

Route::get("/viewer", function() {
	return view("viewer"); 
});

ビルドと実行

以上でView側の設定も完了です。以下のコマンドを実行してフロントエンドのビルドを実行します。

npm run dev

ビルドが完了したら、以下のコマンドを実行し、アプリケーションを起動します。

php artisan serve

「http://127.0.0.1:8000/viewer」にアクセスすると、以下のようにブラウザ上で帳票が出力されます。サイドメニューからPDFなど各種形式への保存も可能です。

おわりに

以上がLaravelでActiveReportsJSを使用して帳票を出力する方法でした。フロントエンドで動作する帳票ライブラリであるActiveReportsJSは様々なWebアプリケーションフレームワークとの連携が可能ですので、気になった方は是非無料のトライアル版をお試しください。