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環境での実装方法を紹介します。
流れは下記です。
- laravel-dompdfのインストール
- 日本語用フォントのインストール
PDFのレイアウトとなるbladeファイルを作成します。
PDF出力を行うロジックを記載します。
そのままでは数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は簡単に実装できるので、ぜひ採用してみてください。
関連記事

参考サイト


コメント