Help us understand the problem. What is going on with this article?

Laravel5.5でPDF出力する

以前、給与計算のアプリを作成したときに、従業員全員の給与と経費をPDF化する機能が必要だったので、ここにメモしておきますー

目次

インストール
コントローラ
ビュー
- CSSの@font-faceを利用する方法
- load_font.phpを使う方法

インストール

今回はlaravel-dompdfライブラリを使います!
https://github.com/barryvdh/laravel-dompdf
composerを使ってパッケージをインストール

composer require barryvdh/laravel-dompdf

config/app.phpprovidersaliasesを編集する

config/app.php
'providers' => [
    ...
    Barryvdh\DomPDF\ServiceProvider::class,
];
'aliases' => [
    ...
    'PDF' => Barryvdh\DomPDF\Facade::class,
];

次にPDF用の設定ファイルを用意しましょう

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

Copied File [/vendor/barryvdh/laravel-dompdf/config/dompdf.php] To [/config/dompdf.php]
Publishing complete.

そうするとconfig/dompdf.phpが作成されるので初期値の設定を変更していきましょう
詳しい設定については以下から確認してみてください
https://github.com/dompdf/dompdf/wiki/UnicodeHowTo#load-a-font-supporting-your-characters-into-dompdf

最初にフォントの設定を確認します

config/dompdf.php
'font_dir' => storage_path('fonts/'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)

これが初期値なので、フォントをインストールしていない場合はfontsディレクトリを作成して、そこに日本語フォントをインストールしましょう
日本語のIPAフォントのダウンロード先はこちらのTTFファイルをダウンロードしてください
https://ipafont.ipa.go.jp/old/ipafont/download.html
2020/09/29時点の四書体パックは下にあります
https://ipafont.ipa.go.jp/IPAfont/IPAfont00303.zip

mkdir storage/fonts
cd storage/fonts
wget https://ipafont.ipa.go.jp/IPAfont/IPAfont00303.zip
unzip IPAfont00303.zip

作成したファイルサイズの肥大化を防ぐために、下の設定も合わせてやりましょう!
またenable_font_subsettingtrueにするとPDFデータに含むフォントファイルを使用しているものに制限できるのでファイルサイズを小さくすることができますー

コントローラ

ExampleController.php
//use PDF;を追記すれば\は必要ない
$pdf = \PDF::loadView('example', compact('example'));
//PDFダウンロードページを新規タブで開く
//return $pdf->stream('PDF名');
//ページ遷移なしでそのままダウンロード
return pdf->download('PDF名');

ダウンロード履歴をDBに保存したい場合はsave()をこの前に記述すればいいですね
このコードの場合はリンクをクリックしたら自動でダウンロードされるので、ページに遷移したけどダウンロードしなかったという履歴が存在しないですね!

それとあまり使うことはないと思いますが、以下のコードを使うこともできます

PDF::loadHTML('<h1>Text Text Text</h1>');

ビュー

CSSの@font-faceを利用する方法

テンプレートのレイアウトを読み込んでしまうと、ずれてしまったので、
テンプレートは読み込まない方がいいと思います!
重要なのはここだけです笑
太文字のために二回@font-faceを指定してください

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style>
@font-face{
    font-family: ipag;
    font-style: normal;
    font-weight: normal;
    src:url('{{ storage_path('fonts/ipag.ttf')}}');
}
@font-face {
font-family: ipag;
font-style: bold;
font-weight: bold;
src: url("{{ storage_path('fonts/IPAfont00303/ipag.ttf') }}") format('truetype');
}
body {
font-family: ipag;
}
</style>

下は実際にテーブル表示をしてみましたー
テーブルは横に切れちゃっていたので全然できないながらもcssで調整しました
参考にはしないでください

長い文章をテーブル内で折り返すには<td>タグにword-breakword-wrapを設定するといいみたいですー

<!DOCTYPE html>
<html lang='ja'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<style type='text/css'>
@font-face {
font-family: ipag;
font-style: normal;
font-weight: normal;
src: url("{{ storage_path('fonts/IPAfont00303/ipag.ttf') }}") format('truetype');
}
@font-face {
font-family: ipag;
font-style: bold;
font-weight: bold;
src: url("{{ storage_path('fonts/IPAfont00303/ipag.ttf') }}") format('truetype');
}
body {
font-family: ipag !important;
}
table th, table td {
padding: 10px 0;
text-align: center;
}
table tr:nth-child(odd) {
background-color: #eee;
}
thead {
display: table-header-group;
}
tfoot {
display: table-row-group;
}
table {
width: 100%;
border-collapse: collapse;
}
th {
word-break: break-all;
word-wrap: break-word;
}
tr {
page-break-inside: avoid;
}
</style>
</head>
<body>
<div align='right'>
出力日時{{ $now }}
</div>
<div align='center'>
{{ $year }}{{ $month }}
<table border=1 align='center'>
<thead>
<tr>
<th>名前</th>
<th>勤務日数</th>
<th>通常時間</th>
<th>深夜時間</th>
<th>総労働時間<br>深夜時間は25%</th>
<th>時給</th>
<th>交通費</th>
<th>バイト代</th>
<th>支給総額</th>
</tr>
</thead>
<tbody>
@foreach ($employees as $employee)
<tr>
<th>{{ $employee->name }}</th>
@if (in_array($employee->id, $activeEmployeesId))
<th>{{ $employees[$employee->id - 1]->count }}</th>
<th>{{ $employees[$employee->id - 1]->normalTime }}</th>
<th>{{ $employees[$employee->id - 1]->nightTime }}</th>
<th>{{ $employees[$employee->id - 1]->totalTime }}</th>
<th>{{ config('common.hourlyFee.100') }}</th>
<th>{{ $employee->expense }}</th>
<th>{{ $employees[$employee->id - 1]->earnings }}</th>
<th>{{ $employees[$employee->id - 1]->totalPayment }}</th>
</tr>
@else
<th>0</th>
<th>0</th>
<th>0</th>
<th>0</th>
<th>
{{ config('common.hourlyFee.100') }}
</th>
<th>0</th>
<th>0</th>
<th>0</th>
</tr>
@endif
@endforeach
</tbody>
<tfoot>
<tr>
<th colspan=4>合計</th>
<th>{{ $sumTime }}</th>
<th></th>
<th>{{ $sumExpense }}</th>
<th>{{ $sumEarnings }}</th>
<th>{{ $sumPayment }}</th>
</tr>
</tfoot>
</table>
</body>
</html>

load_font.phpを使う方法

同様にフォントをダウンロードします
load_font.phpファイルはdomPDFには付属していないので
以下のURLからダウンロードしてください
https://github.com/dompdf/utils
ダウンロードしたファイルを/vendor/dompdf/dompdfの下に保存します
load_font.phpvendor/phenxディレクトリに保存されている
php-font-libphp-svg-libディレクトリが必要みたいなので
vendor/dompdf/dompdf/libにコピーします
下のコマンドを参考にしてください

cd vendor/dompdf/dompdf
git clone https://github.com/dompdf/utils.git
cd lib
cp ../../../phenx/php-font-lib ./ #デフォルトで存在しないフォントを使用する場合に利用するライブラリ
cp ../../../phenx/php-svg-lib ./ #svgをレンダリングするために使用するライブラリ

vendor/dompdf/dompdf/libディレクトリにhtml5lib, php-font-lib, php-svg-libがあることを確認したら
load_font_.phpを実行します

cd ../../../../
php load_font.php ipag storage/fonts/ipag.ttf

うまくいけば、vendor/dompdf/dompdf/lib/fonts/ipag.ufmができていると思います

最後にfontsディレクトリにコピーしておしまい!

cp vendor/dompdf/dompdf/lib/fonts/* storage/fonts/

コントローラーの書き方は先に説明したのと同じで、
ビューの書き方がもう少し簡潔になります

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style>
body {
font-family: ipag;
}
</style>

これでおっけいです
何かとPDF出力するときあると思うので是非試してみてください!

satorunooshie
経済学を学んでいる大学三年生です PHP, Kotlinを中心に学習しています 役に立てそうな英語の記事や詰まったところを共有していきます
https://satorunooshie.net
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away