Laravel8でPDFを出力する(laravel-dompdf)
laravel環境でPDF出力する案件がありましたので、対応方法をご紹介
上記はLaravel-adminの画面ですが、もちろん普通にLaravelで利用できます。
確認済みのLaravelのバージョンは8.Xです。
6.X以降であれば問題なく動作するはずです。
LaravelでPDF出力する方法
パッケージが一番手っ取り早い。有名どころでは下記の2つ
- laravel-dompdf
- Snappy
はじめはSnappyで取り組んでいたのですが、一部うまくいかない部分があったのでlaravel-dompdfへ方針転換
それらを比較するとこんな感じ
larave-dompdf | snappy | |
インストールの手間 | ○ | × |
機能 | △ | ○ |
日本語対応 | × | × |
snappyの方が高機能、らしい。いまのところlarava-dompdfでも不満か感じません。
どちらも海外プラグインのため日本語化するのはパッケージインストール以外に作業が必要です。これが面倒。でも大事な作業なのでがんばりましょう。
Laravel-dompdfのインストール
コマンドこの通り
$ composer require barryvdh/laravel-dompdf Using version ^0.8.5 for barryvdh/laravel-dompdf
インストールが完了したら、サービスプロバイダとエイリアスに登録する必要があります。
両方とも「config/app.php 」ファイルに追記していきます。
まずはサービスプロバイダ部分
'providers' => [ ・ ・ ・ Illuminate\Validation\ValidationServiceProvider::class, Illuminate\View\ViewServiceProvider::class, Barryvdh\DomPDF\ServiceProvider::class,
次にエイリアス部分
'aliases' => [ ・ ・ ・ Illuminate\View\ViewServiceProvider::class, 'Validator' => Illuminate\Support\Facades\Validator::class, 'View' => Illuminate\Support\Facades\View::class, 'PDF' => Barryvdh\DomPDF\Facade::class,
これでインストールと準備が完了しました。
PDFの呼び出し
呼び出し方はbladeテンプレートを呼び出す方法とほとんど同じです。
route設定
まずはroute.phpにパスとコントローラの設定を記述します。今回は顧客氏名などをPDFに出力する必要があったので、パラメータとしてcustomer_idを渡しています。
下記のサンプルはlarave-admin側にコントローラを設定する方法になります。パスにご注意ください。
$router->get('/pdf/dl/{customer_id}', 'PdfController@index')->name('pdf.dl'); $router->get('/pdf/view/{customer_id}', 'PdfController@view')->name('pdf.view');
コントローラ設定
namespace App\Admin\Controllers; use App\Http\Controllers\Controller; use App\Models\Customer; use Barryvdh\DomPDF\Facade as PDF; use Carbon\Carbon; use Encore\Admin\Layout\Content; class PdfController extends Controller { public function index($customer_id) { $customer = Customer::whereId($customer_id)->first(); $date = new Carbon(); $pdf=PDF::loadView('admin.nouhin',compact('customer','date')); return $pdf->download('納品書.pdf'); //こちらがダウンロード用機能 } public function view($customer_id) { $customer = Customer::whereId($customer_id)->first(); $date = new Carbon(); return view('admin.nouhin',compact('customer','date')); //こちらがブラウザ表示用機能 } }
indexがPDFをダウンロードする機能、viewがブラウザ上にそのままPDFを開く機能としています。
Using $this when not in object context エラー
注意事項というより私がはまったこと。
IDE補完機能で「PDF」の宣言に対するインポートをuse宣言していたのですが、気付かぬうちに下記になっていました。
use Barryvdh\DomPDF\PDF;
正しくは上のサンプルにもある通り、Facadeを利用する必要があります。
use Barryvdh\DomPDF\Facade as PDF;
これに気付かず数時間無駄にしました、、
『Error Using $this when not in object context』というエラーに遭遇したらインポート宣言を見直してみてください。
use Barryvdh\DomPDF\PDF
ではなく
use Barryvdh\DomPDF\Facade as PDF;
です!!
laravel-dompdf日本語化
ここまででPDFの出力は完了したかと思います。しかし、出力されたPDFを見ると
?????
のように文字化けしているはずです。海外製プラグインなのでそのままでは日本語が表示できません。
下記の手順で日本語対応が必要です。
load_font.phpダウンロード
IPAフォントをダウンロードします。
明朝とゴシック2つの書体があります。2書体パックをダウンロードしておいた方が後で手間がないかと思います。
ダウンロードしたらLaravelをインストールしたディレクトリ直下にtempなどの適当なディレクトリを作成し保存します。
フォントファイルインストール
$ php load_font.php ipaexg temp/ipaexg.ttf
ゴシックフォントをインストールする場合は「ipaexg」の2か所を「ipaexm」に書き換えてください。
フォントのコピー
load_font.phpを実行してvendor/dompdf/dompdf/lib/fontsディレクトリに作成された、ipagexf.ttf, ipagexg.ufm, dompdf_font_family_cache.phpをstorage/fontsにコピーします。
Bladeテンプレートでフォントを指定
設定が完了したらPDF出力用のテンプレートを修正していきます。このBladeテンプレートでインストールしたフォントをCSSで指定します。
<!doctype html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>PDF</title> <style> body { font-family: ipaexg; } </style> </head> <body> <h1>PDFテスト&lt;/h1> </div> </body> </html>
これで日本語のPDFが出力されるようになりました。
Undefined offset: 12239 エラーが出力される場合
フォントファイルの相性なのか、エラーが出る場合があります。フォントファイルを変更してみましょう。
私はMigMixというフォントを利用させて頂き解消しました。
laravel-dompdf小ネタ
PDFでQRコードを表示する場合の記述
<img src="data:image/png;base64, {{ base64_encode(QrCode::format('png')->size(100)->generate('Make me into an QrCode!')) }} ">
laravel-dompdfまとめ
LaravelからPDF出力する場合にはlarave-dompdfを利用することで対応できるました。日本語化が少し手間ですが、一度慣れてしまえば大丈夫そうです。
HTMLのテンプレートをベースに手軽にPDF出力できるので、ぜひ利用してみてください。