【LaravelでPDF出力】LaravelでPDFを出力する方法を紹介!laravel-dompdfを利用します

【LaravelでPDF出力】LaravelでPDFを出力する方法を紹介!laravel-dompdfを利用します

PDFを出力したい場合が業務などであると思います。

お客様の要望でも多いでしょう。

PDF出力ができればそれを紙として印刷して使用できるので非常に便利です。

今回はLaravelでPDF出力を行う方法を紹介します。

このような方におすすめ
  • WebシステムでPDF出力をしたい
  • LaravelでPDF出力をしたい
  • laravel-dompdfについて知りたい
目次

laravel-dompdfの概要

LaravelでPDF出力を行うにあたって便利なパッケージがあります。

それが「laravel-dompdf」です。

laravel-dompdfはHTMLのものをそのままPDF出力できるもの。

Laravelのbladeで実装したHTMLをそのまま出力できるという非常に便利なライブラリです。

cssももちろん利用できます。

実装方法

ここから実際にLaravel環境での実装方法を紹介します。

流れは下記です。

STEP
インストール
  • laravel-dompdfのインストール
  • 日本語用フォントのインストール
STEP
bladeファイルの作成

PDFのレイアウトとなるbladeファイルを作成します。

STEP
Controllerの作成

PDF出力を行うロジックを記載します。

STEP
ファイルのサイズを小さくする

そのままでは数MBほどの大きなファイルとなってしまうので、サイズを小さくするように変更します。

インストール

sailを利用している場合は、頭に「sail」をつけてください。

下記コマンドでlaravel-dompdfをインストールします。

composer require barryvdh/laravel-dompdf

続いて文字化けしてしまうので日本語用のフォントを入れます。

下記からダウンロードします。

ダウンロード後は「/storage/fonts」にttfファイルを保存します。

bladeファイルの作成

bladeの内容をPDFにそのまま出力することが可能です。

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

<head>
    <meta charset="UTF-8">
    <title>PDFテスト</title>
    <style>
        /* 基本の文字 */
        @font-face {
            font-family: 'NotoSansJP';
            font-style: normal;
            font-weight: normal;
            src: url('{{ storage_path('fonts/NotoSansJP-Regular.ttf') }}');
        }
        @font-face {
            font-family: 'NotoSansJP';
            font-style: bold;
            font-weight: bold;
            src: url('{{ storage_path('fonts/NotoSansJP-Regular.ttf') }}');
        }
        /* 全てのHTML要素に適用 */
        html, body, textarea, table {
            font-family: 'NotoSansJP', sans-serif;
        }
        body {
            padding-top: 5mm;
            width: 190mm;
            height: 297mm;
            margin-left: auto;
            margin-right: auto;
            font-size: 12px;
        }
    </style>
</head>

<body>
    <h1>はじめてのPDF出力</h1>
    <p>PDF出力成功!!!</p>
</body>
</html>

Controllerの作成

Controllerに下記コード追加します。

use Barryvdh\DomPDF\Facade\Pdf;

public function generatePDF()
    {
        $pdf = PDF::loadView('/pdf/test-pdf')
                    ->set_option('compress', 1)
                    ->setPaper('a4', 'portrait'); // 縦A4サイズに指定

        $filename = 'テスト.pdf';

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

Web.phpの設定もお忘れなく。

サイズを小さくする

このままではファイルのサイズが大きいので、dompdfの設定ファイルに変更を加えます。

(sailを利用する場合は、「php」部分を「sail」としてください。

php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider"

configフォルダに「dompdf.php」が作成されたことを確認してください。

下記のようにtrueに変更します。

"enable_font_subsetting" => true

画像を印刷する

画像もPDFとして印刷したい場合、下記の流れで行います。

bladeに直接指定しても画像は表示できません。

理由がbladeを読み込んだ後に画像を読み込むためです。

なのでコントローラーからエンコードした画像ファイルをbladeに渡して表示する形にします。

Controller

(storageフォルダ内に画像を置いているパターンです。)

public function generatePDF()
    {
        $image_path = storage_path('app/public/image/任意のファイルパス');
        $image_data = base64_encode(file_get_contents($image_path));

        $pdf = PDF::loadView('/pdf/test-pdf', compact('image_data'))
                    ->set_option('compress', 1)
                    ->setPaper('a4', 'portrait'); // 縦A4サイズに指定

        $filename = 'テスト.pdf';

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

blade.php

<body>
    <h1>はじめてのPDF出力</h1>
    <p>PDF出力成功!!!</p>
    <img src="data:image/jpeg;base64,{{ $image_data }}" alt="任意の名前" width="300" height="300">
</body>

画像のサイズは適宜変更してください。

これで画像が表示されたと思います。

コントローラー側で画像をエンコーディングして、blade側でエンコーディングされた画像を展開するような形となります。

画像ファイルの置き場所は好きな場所で大丈夫です。

ユーザが任意のファイルをアップロードしてPDF出力

ユーザが好きな画像をアップロードしたい場合の処理を紹介します。

bladeに下記を追加します。

<input class="Form-Item-Input" type="file" name="image">

コントローラーには下記のように編集します。

$file = $request->file('image');

        // アップロードされたファイル名を取得
        $file_name = $request->file('image')->getClientOriginalName();
        $file_path = Storage::disk('public')->putFileAs('images', $file, $file_name);

        // [sail artisan storage:link]コマンドでストレージフォルダにアクセス可能とする
        $image_data = base64_encode(file_get_contents('storage/'. $file_path));

        $pdf = PDF::loadView('/service/diary/service-diary-pdf-preview', compact('request', 'image_data'))
                    ->set_option('compress', 1)
                    ->setPaper('a4', 'portrait'); // 縦A4サイズに指定

        return $pdf->download($request->title.'.pdf');

ターミナルで下記コマンドを実行してストレージフォルダへのアクセスを可能とします。

sail artisan storage:link

処理流れを下記に記します。

  • 「$file_name = $request->file(‘image’)->getClientOriginalName();」
    →ファイル名を取得します
  • 「$file_path = Storage::disk(‘public’)->putFileAs(‘images’, $file, $file_name);」
    →storage/public/imagesフォルダにアップロードされた画像を保存します。
  • $image_data = base64_encode(file_get_contents(‘storage/’. $file_path));
    →画像をエンコーディングします。

あとは出力用のbladeにエンコーディングした画像を渡してあげるだけで表示できます。

複数ファイルのアップロード

bladeを編集します。

<input class="Form-Item-Input" type="file" name="image[]" multiple>

複数ファイルに対応するには「multiple」を付けます。

さらにname属性には[]をつけて配列で渡すようにします。

コントローラー側では下記のように編集します。

public function generatePDF(Request $request)
    {
        $files = $request->file('image');

        // アップロードされたファイル名を取得
        $file_names = [];
        $image_datas = [];
        foreach ($files as $file) {
            $file_name = $file->getClientOriginalName();
            $file_names[] = $file_name;
            $file_path = Storage::disk('public')->putFileAs('images', $file, $file_name);

            // [sail artisan storage:link]コマンドでストレージフォルダにアクセス可能とする
            $image_datas[] = base64_encode(file_get_contents('storage/'. $file_path));
        }

        $pdf = PDF::loadView('/service/diary/service-diary-pdf-preview', compact('request', 'image_datas'))
                    ->set_option('compress', 1)
                    ->setPaper('a4', 'portrait'); // 縦A4サイズに指定

        // ストレージ内のファイルを削除
        foreach ($file_names as $file_name) {
            Storage::disk('public')->delete('/images/'. $file_name);
        }

        return $pdf->download($request->title.'.pdf');
    }

最後にPDF出力用のbladeを編集します。

@foreach ($image_datas as $image_data)
        <img src="data:image/jpeg;base64,{{ $image_data }}" alt="画像" width="300">
    @endforeach

まとめ

今回はlaravel-dompdfでPDF出力を実装しました。

他にもライブラリはありますが、個人的にはlaravel-dompdfがおすすめです。

「Chrome-PHP」というものも便利そうで良かったんですが、私はなぜか上手くいきませんでした。

laravel-dompdfは簡単に実装できるので、ぜひ採用してみてください。

関連記事

参考サイト

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

フリーランスエンジニアとして活動。
主に業務システムの要件定義~保守まで幅広く担当しています。
お気軽にお問い合わせください。

【趣味】
筋トレ/読書/プログラミング/資格の勉強

コメント

コメントする

目次