Laravel 2026.06.22

LaravelでPDF請求書を自動生成!印刷して終わりにする実装術

約4分で読めます

毎月の請求書作成を自動化したい中小企業の担当者へ。LaravelとDomPDFを使えば、データ入力からPDF出力まで一気通貫で実現できます。実案件ベースで解説します。

「今月も請求書、手作業ですか?」

こんな悩みはありませんか?

  • Excelで請求書を作るたびに日付・金額を手打ちしている
  • メールで送った後、印刷用PDFを別途作り直している
  • 担当者が変わるたびにフォーマットがバラバラになる
  • 月末になると「請求書地獄」が始まって他の業務が止まる

これはよくある風景です。しかし実は、すでにLaravelで社内システムや受注管理を動かしているなら、追加の工数なしにPDF請求書の自動生成を組み込める可能性が高いです。

本記事では、神奈川のWebシステム開発を20年以上手がけてきた弊社の実案件をベースに、「データベースの情報を取得してPDFに落とし込み、印刷ボタンを押すだけで終わる」仕組みの作り方を解説します。


なぜ手作業の請求書作成が問題なのか

一見「Excelで十分では?」と思われがちですが、手作業の運用にはじわじわと積み重なるコストがあります。

取引先が20社程度でも、月に3時間前後を請求書まわりに消費しているケースは珍しくありません。さらに見落としがちな問題として「人的ミスのリスク」があります。金額の転記ミス、消費税の計算違い、宛名の打ち間違い――これらは取引先との信頼に直結します。

システムで自動生成にした場合、入力はデータベースへの1回のみ。PDF化・フォーマットの統一・再発行もすべてボタン一発です。弊社が支援したある神奈川の製造系中小企業では、導入後に月次の請求処理時間が約70%削減され、経理担当者が本来の業務に集中できるようになりました。


Laravelの開発・保守でお困りですか?

アップグレード代行・機能追加・パフォーマンス改善など、お気軽にご相談ください

無料で相談する

実装の全体像:LaravelとDomPDFの組み合わせ

LaravelでPDFを扱う際、最も広く使われているのが barryvdh/laravel-dompdf パッケージです。BladeテンプレートをそのままPDFに変換できるため、HTML/CSSの知識があれば美しい帳票を作成できます。

ステップ1:パッケージのインストール

composer require barryvdh/laravel-dompdf

インストール後、config/app.php に明示的にプロバイダーを追加する必要はなく(Laravel 5.5以降は自動検出)、すぐに使い始められます。

ステップ2:請求書データを整形するコントローラー

実案件では Invoice モデルと InvoiceItem(明細)モデルの1対多リレーションで管理しています。

<?php

namespace App\Http\Controllers;

use App\Models\Invoice;
use Barryvdh\DomPDF\Facade\Pdf;

class InvoicePdfController extends Controller
{
    public function download(Invoice $invoice)
    {
        // リレーションを一括取得してN+1問題を防ぐ
        $invoice->load(['client', 'items', 'items.product']);

        // 消費税・合計金額を計算して渡す
        $subtotal = $invoice->items->sum(fn($item) => $item->unit_price * $item->quantity);
        $tax      = (int) round($subtotal * 0.10);
        $total    = $subtotal + $tax;

        $pdf = Pdf::loadView('pdfs.invoice', compact('invoice', 'subtotal', 'tax', 'total'))
            ->setPaper('a4', 'portrait')
            ->setOption('defaultFont', 'dejavu sans'); // 日本語対応フォント指定

        $filename = '請求書_' . $invoice->invoice_number . '.pdf';

        return $pdf->download($filename);
    }
}

ステップ3:BladeテンプレートでPDFレイアウトを作る

resources/views/pdfs/invoice.blade.php を作成します。CSSは <style> タグにインライン記述するのがDomPDF向けのベストプラクティスです。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <style>
        body  { font-family: 'dejavu sans'; font-size: 12px; color: #333; }
        .header { text-align: right; margin-bottom: 20px; }
        .title  { font-size: 24px; font-weight: bold; text-align: center; margin: 20px 0; }
        table   { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td  { border: 1px solid #ccc; padding: 8px; text-align: left; }
        th      { background-color: #f0f0f0; }
        .total-row { font-weight: bold; background-color: #fff9e6; }
        .footer { margin-top: 40px; font-size: 10px; color: #777; }
    </style>
</head>
<body>
    <div class="header">
        <p>発行日:{{ $invoice->issued_at->format('Y年m月d日') }}</p>
        <p>請求書番号:{{ $invoice->invoice_number }}</p>
    </div>

    <div class="title">請 求 書</div>

    <p>{{ $invoice->client->name }} 御中</p>

    <table>
        <thead>
            <tr>
                <th>品目</th>
                <th>数量</th>
                <th>単価</th>
                <th>金額</th>
            </tr>
        </thead>
        <tbody>
            @foreach ($invoice->items as $item)
            <tr>
                <td>{{ $item->description }}</td>
                <td>{{ $item->quantity }}</td>
                <td>¥{{ number_format($item->unit_price) }}</td>
                <td>¥{{ number_format($item->unit_price * $item->quantity) }}</td>
            </tr>
            @endforeach
        </tbody>
        <tfoot>
            <tr class="total-row">
                <td colspan="3">小計</td>
                <td>¥{{ number_format($subtotal) }}</td>
            </tr>
            <tr class="total-row">
                <td colspan="3">消費税(10%)</td>
                <td>¥{{ number_format($tax) }}</td>
            </tr>
            <tr class="total-row">
                <td colspan="3"><strong>合計</strong></td>
                <td><strong>¥{{ number_format($total) }}</strong></td>
            </tr>
        </tfoot>
    </table>

    <div class="footer">
        <p>お支払い期限:{{ $invoice->due_at->format('Y年m月d日') }}</p>
        <p>振込先:○○銀行 △△支店 普通 1234567 カブシキガイシャ〇〇</p>
    </div>
</body>
</html>

ステップ4:ルートを追加してダウンロードを有効化

// routes/web.php
Route::get('/invoices/{invoice}/pdf', [InvoicePdfController::class, 'download'])
    ->name('invoices.pdf')
    ->middleware('auth');

これだけです。管理画面の「PDF出力」ボタンにこのURLをリンクすれば、クリック → 印刷の2ステップで業務が完了します。


よくある失敗パターンと対処法

DomPDFのデフォルトフォントは日本語非対応です。`setOption('defaultFont', 'dejavu sans')` を指定するか、IPAexフォントなどをDomPDFのフォントディレクトリに追加してください。`config/dompdf.php` の `font_dir` と `font_cache` が書き込み可能なパスになっているかも要確認です。
相対パスは機能しません。`public_path('images/logo.png')` で絶対パスに変換してHTMLに埋め込むか、Base64エンコードして `<img src="data:image/png;base64,...">` の形式にしてください。
DomPDFはCSS Grid・Flexboxの対応が限定的です。レイアウトは `<table>` ベースで組むのが安全策。明細行数が多い場合は `page-break-inside: avoid` を適切に設定しましょう。
大量データの集計処理をコントローラーに直書きしていると、処理時間が長くなります。集計はモデルのスコープやキャッシュで最適化し、PDF生成はキューに投げてStorageに保存→通知という非同期パターンに切り替えると安定します。
発行済み請求書はDBの `locked` フラグや `status` カラムで更新を禁止し、再発行は新しい請求書番号で起票するフローにしましょう。会計処理の整合性を守る上で重要です。

自動生成の効果:導入前後の比較

残りの28%は「銀行口座の確認」「未払いのフォロー電話」など、人が判断すべき業務です。システムはあくまで定型作業を人から解放する道具と捉えるのが正解で、すべてを自動化しようとすると逆に複雑になりすぎます。


Laravelの開発・保守でお困りですか?

アップグレード代行・機能追加・パフォーマンス改善など、お気軽にご相談ください

無料で相談する

この技術、御社の業務にも活かせます

業務システム開発

Laravelを使った業務システムの構築・改修を20年以上の経験でサポートします

200件以上の制作実績 顧客満足度97% 初回相談無料

※ 通常1営業日以内にご返信します

まとめ:まず何から始めるか

Laravelで請求書PDFを自動生成する実装は、難易度のわりにリターンが大きいタスクです。既存の受注・顧客データを活用できるなら、初期実装は1〜3日程度で動くものが作れます。

まず以下のチェックリストで自社の状況を確認してみてください。

「LaravelはあるけどPDF化までは手が回っていなかった」「既存システムに請求機能を追加したい」といったご相談は、ぜひ弊社Fivenine Designまでお気軽にどうぞ。神奈川を拠点に20年以上、中小企業の業務効率化を伴走してきた経験を活かして、貴社の「印刷して終わり」を実現します。

この記事をシェア

Laravelの開発・運用、プロに任せませんか?

システム構築からバージョンアップまで、経験豊富なエンジニアがサポートします。 初回相談は無料です。

※ 1営業日以内にご返信いたします

この技術でお困りなら

無料でプロに相談できます

相談する
AIに無料相談