前回の記事、そうだ、そうだ、Laravel Excelを使ってみよう(1)セットアップの続きです。

ヘッダ行を追加

前回出力したファイル storage/app/purchase_history.xlsx を見るとデータのみが出力されていて、各列が何を示すのか分かりません。ヘッダ行を追加して分かりやすくします。WithHeadingsインタフェースを追加し、以下のメソッドをExportクラスに追加します。WithHeadingsインタフェースの制約により、戻り値の型をarrayに指定する必要があるのでご注意を。

...
use Maatwebsite\Excel\Concerns\WithHeadings;

class PurchaseHistoryExport implements FromCollection, WithHeadings
{
    /**
     * @return array
     */
    public function headings() :array
    {
        return [
            'ID', '作成日', '更新日', 'user_id', '商品名', '単価', '数量'
        ];
    }
 ...

再度tinkerから出力するとヘッダ行が追加されました。

こちら出力して気づいたのですが、「数量」列に空欄になっているセルがありますね。なんでしょう?tinkerで該当のレコードを確認してみます。

Psy Shell v0.10.6 (PHP 7.2.34 — cli) by Justin Hileman
>>> App\PurchaseHistory::find(7);
=> App\PurchaseHistory {#4090
     id: 7,
     created_at: "2021-03-15 09:45:05",
     updated_at: "2021-03-15 09:45:05",
     user_id: 42426926,
     product_name: "provident",
     price: 5352,
     quantity: 0,
   }

なるほど、quantity: 0になっている箇所が空欄になっているのですね。Laravel Excelではデフォルトでは0をエクスポートするとnull扱いされ空のセルとなります。0を0として出力したい場合はWithStrictNullComparisonインタフェースをimplementする必要があります。

...
use Maatwebsite\Excel\Concerns\WithStrictNullComparison;

class PurchaseHistoryExport implements FromCollection, WithHeadings, WithStrictNullComparison
{
...

再度エクスポートすると空欄だったセルに0が挿入されています

ここまででお気づきかもしれませんが、Laravel Excelの実装は基本的にインタフェース(公式ドキュメントではConcernと呼ばれている)を追加していきます。必要なものを必要な時にだけ、最小限の拡張で実装できるのでコードをシンプルに保つことができそうです。

行ごとの処理を追加

前項まではDBから取得したデータをそのまま出力していましたが、「更新日・単価・数量」は不要、代わりに「合計金額」を出力して欲しい、と依頼されたとします。行ごとの処理を追加して出力内容を修正してみましょう。(この程度であれば、collectionメソッド側でDBから取得する際のクエリを修正した方が効率的ですが、例の為に敢えて行ごとの処理として実装します。)

エクスポートする項目が変わるのでヘッダ行の設定を先に修正します。

public function headings() :array
{
    return [
        'ID', '作成日', 'user_id', '商品名', '合計金額',
    ];
}

次に、行ごとの処理を追加します。行ごとの処理はWithMappingインタフェースをimplementし、mapメソッドを追加して実装です。合計金額は単価 x 数量としました。

...
use Maatwebsite\Excel\Concerns\WithMapping;

class PurchaseHistoryExport implements FromCollection, WithHeadings, WithStrictNullComparison, WithMapping
{
...

    /**
     * @param PurchaseHistory $row
     * @return array
     */
    public function map($row) :array
    {
        return [
            $row->id,
            $row->created_at,
            $row->user_id,
            $row->product_name,
            $row->price * $row->quantity, // 合計金額
        ];
    }
...

エクスポートは以下になりました。

更に続きます。

By hikaru