Laravelでlaravel-dompdfを使用して、PDFを作成したので使い方をまとめました。
最初の方に、導入方法と実際にPDF出力の動作確認を書いて、後半に使いそうな内容をいくつか書いています。
載せているサンプルコードはLaravelのバージョン8で検証しています。
ライブラリのgithubはこちらです。
barryvdh/laravel-dompdf
laravel-dompdfの導入と設定
composerを使って、プロジェクトに導入したあとに、config/app.php
に対して設定を行います。
インストールする
下記コマンドをプロジェクト配下で実行します。
$ composer require barryvdh/laravel-dompdf
実行すると、インストールが終わって下記のように表示されます。
$ composer require barryvdh/laravel-dompdf
Using version ^0.9.0 for barryvdh/laravel-dompdf
./composer.json has been updated
Running composer update barryvdh/laravel-dompdf
# ---省略---
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
75 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
composer.json
に"barryvdh/laravel-dompdf
が入っていることが確認できます。
"require": {
"barryvdh/laravel-dompdf": "^0.9.0",
}
設定する
config/app.php
を開いて、インストールしたライブラリが使用できるように設定します。
providers
項目に下記のようにライブラリを追加します。
'providers' => [
//---省略---
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
//---ここから追加する---
Barryvdh\DomPDF\ServiceProvider::class,
//---ここまで追加する---
],
aliases
項目のこちらにも、インストールしたライブラリを追加します。
'aliases' => [
//---省略---
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
//---ここから追加する---
'PDF' => Barryvdh\DomPDF\Facade::class,
//---ここまで追加する---
],
これで、PDFを出力する準備が完了しました。
日本語を表示するための設定
日本語を表示するためには、フォントファイルが必要です。
今回は、下記のフォントをダウンロードして使わせてもらいました。
M+とIPAの合成フォント
太字をPDFに表示するためには、フォントに太字のものが必要です。
migmix-2p-20200307.zip
をダウンロードしました。
そして、下記の2つのフォントファイルをstorage/fonts
配下に配置しました。
・migmix-2p-bold.ttf
HTML(bladeファイル)からPDFを出力する
bladeのHTMLからPDFファイルを出力することができます。
今回は、このHTMLからPDFを作成する機能を使って、PDF出力しました。
コントローラーを作成する
出力のためのコントローラーを作成しました。
artisan
コマンドで作成することができます。
$ php artisan make:controller PdfOutputController
app/Http/Controllers/PdfOutputController.php
にコントローラーが出来上がるので、下記のように編集しました。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PdfOutputController extends Controller
{
public function output() {
$sushiTable = [
'たまご' => '100円',
'いくら' => '200円',
'サーモン' => '180円',
'いか' => '100円',
'マグロ' => '110円',
'えび' => '100円',
];
$pdf = \PDF::loadView('pdf_output', ['sushiTable' => $sushiTable]);
$pdf->setPaper('A4');
return $pdf->stream();
}
}
解説
output
メソッドにPDF出力のための処理を書きました。
まず、bladeに渡したい値を配列で作成しました。お寿司のネタと値段を入れた配列です。
その後に、インストールしたPDFライブラリを使っています。
loadView
メソッドの第1引数にbladeファイルの名前、第2引数に渡したい値を連想配列で渡します。
作成したPDFクラスのインスタンスのsetPaper
メソッドで用紙のサイズを指定しています。
今回はA4です。
最後にstreamメソッドを使用して、return $pdf->stream()
としています。
こうすることで、ブラウザのPDFプレビューモードで開くようになります。
HTML(blade)ファイルを作成する
resources/views
配下にpdf_output.blade.php
という名前でbladeファイルを作成しました。
内容は下記になります。
<html lang="ja">
<head>
<title>pdf output test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style>
@font-face{
font-family: migmix;
font-style: normal;
font-weight: normal;
src: url("{{ storage_path('fonts/migmix-2p-regular.ttf')}}") format('truetype');
}
@font-face{
font-family: migmix;
font-style: bold;
font-weight: bold;
src: url("{{ storage_path('fonts/migmix-2p-bold.ttf')}}") format('truetype');
}
body {
font-family: migmix;
line-height: 80%;
}
.main_image {
width: 100%;
text-align: center;
margin: 10px 0;
}
.main_image img{
width: 90%;
}
.sushiTable {
border: 1px solid #000;
border-collapse: collapse;
width: 50%;
}
.sushiTable tr th{
background: #87cefa;
padding: 5px;
border: 1px solid #000;
}
.sushiTable tr td{
padding: 5px;
border: 1px solid #000;
}
</style>
</head>
<body>
PDFの出力テスト!<br>
<div style="font-weight:bold">ここは太字!</div>
<div class="main_image">
<img src="https://codelikes.com/wp-content/uploads/2019/06/PHP-e1601051806241.jpg" />
</div>
お寿司のテーブル
<table class="sushiTable">
<tr>
<th>名前</th>
<th>価格</th>
</tr>
@foreach ($sushiTable as $key => $value)
<tr>
<td>{{ $key }}</td><td>{{ $value }}</td>
</tr>
@endforeach
</table>
</body>
</html>
解説
下記の箇所で、インストールして配置したフォントを読み込んでいます。
storage_pathヘルパーを使用することで、storage配下のファイルにアクセスできます。
フォントファイルを通常用と太字用で、それぞれ読み込みました。
@font-face{
font-family: migmix;
font-style: normal;
font-weight: normal;
src: url("{{ storage_path('fonts/migmix-2p-regular.ttf')}}") format('truetype');
}
@font-face{
font-family: migmix;
font-style: bold;
font-weight: bold;
src: url("{{ storage_path('fonts/migmix-2p-bold.ttf')}}") format('truetype');
}
読み込んだフォントをbodyタグの全体に使うようにしています。
body {
font-family: migmix;
line-height: 80%;
}
後はCSSとしては、画像の位置やテーブルのボーダーなどを定義しました。
下記のように、bladeの書き方ができるので、if文を使用したりすることも可能です。
@foreach ($sushiTable as $key => $value)
<tr>
<td>{{ $key }}</td><td>{{ $value }}</td>
</tr>
@endforeach
今回はforeach
で渡された配列から、キーと値を取得して表示するようにしています。
PDF出力のルートを作成する
routes/web.php
を開いて、今回作ったコントローラーへのルーティングを追加します。
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers;
use App\Http\Controllers\PdfOutputController;
Route::get('/output/pdf', [PdfOutputController::class, 'output']);
/output/pdf
にアクセスしたら、PdfOutputControllerのoutputメソッドを実行してくれます。
動作確認する
ローカルで動作確認してみました。
`http://localhost:8000/output/pdf`にアクセスします。
そうすると、このようにPDFファイルが出力されました。
ちゃんと日本語出力できて、CSSが効いていますね。
用紙のサイズ・向きを変更する
サンプルコードで書いたように、setPaper
メソッドで用紙のサイズを指定可能です。
また、横向きにするには、第2引数にlandscape
を指定します。
$pdf->setPaper('A4', 'landscape');
用紙のサイズについてはvendor/dompdf/dompdf/src/Adapter/CPDF.php
に定義があるのを発見しました。
$PAPER_SIZES
に定義されている内容を設定できるようです。
static $PAPER_SIZES = [
"4a0" => [0, 0, 4767.87, 6740.79],
"2a0" => [0, 0, 3370.39, 4767.87],
"a0" => [0, 0, 2383.94, 3370.39],
"a1" => [0, 0, 1683.78, 2383.94],
"a2" => [0, 0, 1190.55, 1683.78],
"a3" => [0, 0, 841.89, 1190.55],
"a4" => [0, 0, 595.28, 841.89],
"a5" => [0, 0, 419.53, 595.28],
"a6" => [0, 0, 297.64, 419.53],
"a7" => [0, 0, 209.76, 297.64],
"a8" => [0, 0, 147.40, 209.76],
"a9" => [0, 0, 104.88, 147.40],
"a10" => [0, 0, 73.70, 104.88],
"b0" => [0, 0, 2834.65, 4008.19],
"b1" => [0, 0, 2004.09, 2834.65],
"b2" => [0, 0, 1417.32, 2004.09],
"b3" => [0, 0, 1000.63, 1417.32],
"b4" => [0, 0, 708.66, 1000.63],
//---省略---
];
余白を制御する
PDFで作成したページの上下左右の余白を調整したい場合です。
CSSで下記のようにすることで、制御可能です。
@page {
margin: 10px;
}
ここでは、上下左右に10px余白を取るようにしました。
このようにmargin
で調整ができます。
改ページする
改ページさせたい場合にはCSSのpage-break-after
を使用します。
例えば、今回作成したサンプルの画像とテーブルを分けたい場合は、下記のようにします。
PDFの出力テスト!<br>
<div style="font-weight:bold">ここは太字!</div>
<div class="main_image">
<img src="https://codelikes.com/wp-content/uploads/2019/06/PHP-e1601051806241.jpg" />
</div>
<div style="page-break-after: always"></div>
お寿司のテーブル
<table class="sushiTable">
<tr>
<th>名前</th>
<th>価格</th>
</tr>
@foreach ($sushiTable as $key => $value)
<tr>
<td>{{ $key }}</td><td>{{ $value }}</td>
</tr>
@endforeach
</table>
下記のpage-break-after: always
がスタイルとして、つけられているタグの箇所で改ページされます。
<div style="page-break-after: always"></div>
結果として、このように分けられます。
ダウンロードさせる
プレビュー表示ではなくて、ダウンロードさせたい場合です。
その場合は、streamメソッドを呼ぶのではなく、downloadメソッドを呼んで返すようにします。
return $pdf->download();
保存していない画像(base64)を表示したい
base64を使用して、画像を表示することが可能です。
この場合は開発している環境に、PHPのgdライブラリが入っていないとエラーになるので注意です。
bladeファイルのimgタグに、下記のようにbase64画像の文字列を入れると表示されます。
png
画像なら下記のように指定します。
<img src="data:image/png;base64,[base64画像テキスト]" />
画像をbase64文字列にするためのサンプルは下記になります。
[php]画像をbase64_encodeする
コメント