Laravelがインストール済みの環境で動作確認を行います。動作確認を行ったLaravelのバージョンはLaravel6.x, Laravel5.7です。

Laraveでアプリケーションを構築している際にデータベースに保存したデータを利用してPDFファイルを作成したいという要望は非常にたくさんあります。例えば、請求書や納品書といった帳票データの作成です。そんな時にLaravel-dompdfパッケージを利用することで帳票データをPDFで作成することができます。

laravel-dompdfパッケージのインストールと設定

laravel-dompdfパッケージのインストール

larave-dompdfパッケージのインストールはcomposerを使用して行います。インストールにはcomposer requireコマンド使用し、パッケージにはbarryvdh/laravel-dompdfを指定します。


$ composer require barryvdh/laravel-dompdf
Using version ^0.8.5 for barryvdh/laravel-dompdf
 ・
 ・

サービスプロバイダーとエイリアスへの登録

インストール完了後、Laravelインストールディレクトリのconfig\app.phpにサービスプロバイダーとエイリアスを登録する必要があります。

providersには、Barryvdh\DomPDF\ServiceProvider::classの追加。aliasesには、’PDF’ => Barryvdh\DomPDF\Facade::classの追加を行います。


   'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
            ・
        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
            ・
        App\Providers\RouteServiceProvider::class,
        Barryvdh\DomPDF\ServiceProvider::class,
    ],

    /*
    |--------------------------------------------------------------------------
    | Class Aliases
    |--------------------------------------------------------------------------
    |
    | This array of class aliases will be registered when this application
    | is started. However, feel free to register as many as you wish as
    | the aliases are "lazy" loaded so they don't hinder performance.
    |
    */

    'aliases' => [
        'App' => Illuminate\Support\Facades\App::class,
            ・
        'View' => Illuminate\Support\Facades\View::class,
        'PDF' => Barryvdh\DomPDF\Facade::class,
    ],
];

PDFの作成

ここまでの手順でPDFを作成するための設定は完了しました。次はController(コントローラー)を使って実際にPDFが作成できるか確認を行いましょう。

Controller(コントローラー)の作成

PDFの作成を行うため、php artisan make:controllerコマンドを使って、コントローラーの作成を行います。


$ php artisan make:controller PDFController

ルーティングの設定

コントローラーファイルを作成後、web.phpを使ってルーティングの追加を行います。


Route::get('pdf','PDFController@index');

ブラウザ上にPDFを表示

ブラウザ上にPDFファイルの内容を表示させるためにPDFControllerに以下を記述します。Hello Worldをh1タグで囲んでPDFファイルに大きなHello Worldの文字列を表示させます。


<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use PDF;

class PDFController extends Controller
{
    public function index(){

    	$pdf = PDF::loadHTML('<h1>Hello World</h1>');

    	return $pdf->stream();

    }
}

php artisan serveコマンドで開発サーバの起動を行います。


$ php artisan serve
Laravel development server started: http://127.0.0.1:8000

先ほど設定したルーティングのhttp://127.0.0.1:8000/pdfにアクセスするとlaravel-dompdfで作成されたPDFがブラウザ上に表示されます。

PDFにHello Worldを表示
PDFにHello Worldを表示

PDFのダウンロード

先ほどはブラウザにPDFファイルの内容を表示させましたが、今度は/pdfにアクセスするとPDFファイルがダウンロードされる設定へと変更を行います。

PDFController.phpファイルに記述したstreamメソッドをdownloadメソッドに変更します。dowloadメソッドの引数にファイル名を入力すると入力したファイル名でPDFをダウンロードすることができます。


$pdf = PDF::loadHTML('<h1>Hello World</h1>');

return $pdf->download('hello.pdf');

設定に問題がなければ http://127.0.0.1:8000/pdf にアクセスするとPDFファイルがダウンロードされます。

日本語の内容のPDFを作成

日本語で記載された文章でも表示されるか確認するためにh1タグ内の文字のみ日本語に変更を行います。


$pdf = PDF::loadHTML('<h1>こんにちは</h1>');

 return $pdf->stream();

残念ながら、初期設定のままでは文字化けを起こして日本語化することができませんでした。

PDFを作成すると文字化け
PDFを作成すると文字化け

日本語化への対応方法

PDFが簡単に作成できたとしても日本語に対応していなければ、本番環境で使用することはできません。日本語のPDFが作成できるように設定を行いましょう。

設定については、A guide to enabling Unicode support in DOMPDFを参考に行っています。

日本語化には、load_font.phpスクリプトを使用した方法とCSSの@font-faceを利用した2つの方法がありますが、先に@font-faceを使用した方法の説明を行い、後でload_font.phpスクリプトを使用した方法を説明します。
fukidashi

fontsディレクトリの作成

インストールディレクトリにあるstorageディレクトリの下にfontsディレクトリを作成します。


$ mkdir fonts

IPAフォントのダウンロード

日本語フォントのIPAフォントのダウンロードを行います。URLは、https://moji.or.jp/ipafont/ipa00303/です。

ページの中盤になるTFTファイルのダウンロードを行ってください。

IPAフォントダウンロード
IPAフォントダウンロード

zipファイルとしてダウンロードされるので、解凍後、その中にあるファイルを先ほど作成したstorage/fonts/ディレクトリの下にコピーしてください。

CSSの@font-faceを利用した場合

Bladeファイルを利用したPDFの作成

CSSの@font-faceを利用して、日本語化するためにBladeファイルを利用してPDFの作成を行います。loadViewメソッドを利用して引数には、Viewのファイル名を入力します。ファイル名には、helloを設定しているので、resources\viewディレクトリにhello.blade.phpの作成を行います。


$pdf = PDF::loadView('hello');

return $pdf->download('hello.pdf');

view.blade.phpファイルは下記の通りに記述します。@font-faceを使って使用するフォントの設定を行います。storage_pathにはIPAフォントを保存したstorage/fontsを指定してください。


<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>PDF</title>
<style>
@font-face{
    font-family: ipag;
    font-style: normal;
    font-weight: normal;
    src:url('{{ storage_path('fonts/ipag.ttf')}}');
}
body {
font-family: ipag;
}
</style>
</head>
<body>
    <p>こんにちは</p>
</div>
</body>
</html>

日本語フォントを設定する前には、文字化けが発生していましたが、設定完了後は正常に日本語が表示されました。

日本語化成功
日本語化成功

font-weight問題

pタグで囲んだ文字列は正常に表示されますが、h1タグのようにfont-weightがboldに設定されているフォントについては、文字化けが発生してしまいます。font-weightを複数設定したい場合は、下記のようにfont-faceも複数設定する必要があります。しかし、font-weightの設定を変えても文字化けは発生しませんが、文字の太さは変わりません。


<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>PDF</title>
<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/ipag.ttf')}}');
}
body {
font-family: ipag;
}
</style>
</head>
<body>
    <h1>こんにちは</h1>
</div>
</body>
</html>

load_font.phpを利用した場合

load_font.phpのダウンロード

load_font.phpをdompdf-utils projectからダウンロードする必要があります。

ダウンロードしたload_font.phpファイルは、Laravelをインストールしたディレクトリに保存します。また、IPAのダウンロードしたフォントも適当なディレクトリを作成し、その場所に保存してください。ここではtmpディレクトリを作成し、そこに保存しています。

load_font.phpを開くと一番上で、vendor/autoload.phpをrequire_onceしています。そのため、Laravelのインストールディレクトリに保存して実行します。
fukidashi

フォントのインストール

下記のコマンドを実行して、IPAGフォントのインストールを行います。/tmp/ipag.ttfの部分は保存した場所によって変更を行ってください。


$ php load_font.php ipag tmp/ipag.ttf

実行後、unable to find(みつけることができない)といったメッセージが出力されます。


Unable to find bold face file.
Unable to find italic face file.
Unable to find bold_italic face file.
Copying tmp/ipag.ttf to /XXXXXXX/vendor/dompdf/dompdf/lib/fonts/ipag.ttf...
Generating Adobe Font Metrics for /XXXXXXX/vendor/dompdf/dompdf/lib/fonts/ipag...

/vendor/dompdf/dompdf/lib/fontsに移動し、dompdf_font_family_cache.phpファイルを確認するとインストールしたipadフォントの情報が追加されていることを確認できます。


  'ipag' => array(
    'normal' => $fontDir . '/ipag',
    'bold' => $fontDir . '/ipag',
    'italic' => $fontDir . '/ipag',
    'bold_italic' => $fontDir . '/ipag',
  ),

フォントのコピー

load_font.phpを実行してvendor/dompdf/dompdf/lib/fontsディレクトリに作成された、ipag.ttf, ipag.ufm, dompdf_font_family_cache.phpをstorage/fontsにコピーします。

Bladeファイルを利用したPDFの作成

Bladeファイルを利用してPDFの作成を行います。loadViewメソッドを利用して引数には、Viewのファイル名を入力します。ファイル名には、helloを設定しているので、resources\viewディレクトリにhello.blade.phpの作成を行います。


$pdf = PDF::loadView('hello');

return $pdf->donwload('hello.pdf');

view.blade.phpファイルは下記の通りに記述します。load_font.phpの場合は@font-faceを設定する必要がないかためheadタグ部分がシンプルになります。


<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>PDF</title>
<style>
body {
font-family: ipag;
}
</style>
</head>
<body>
    <h1>こんにちは</h1>
</div>
</body>
</html>
日本語化成功
日本語化成功

PDFのファイルサイズ問題

日本語化はできましたが、作成したファイルのサイズを確認すると4.5MBになっています。日本語のフォントがすべてPDFにも埋め込まれているためサイズが大きくなっています。埋め込みをなくすためには、dompdfの初期設定を変更する必要があります。下記のコマンドを実行することでconfigディレクトリの中にdompdfの設定ファイルdompdf.phpを作成します。


$ php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider"
Copied File [/vendor/barryvdh/laravel-dompdf/config/dompdf.php] To [/config/dompdf.php]
Publishing complete.

dompdf.phpファイルを開いて、enable_font_subsettingをfalseからtrueに設定変更します。


* Whether to enable font subsetting or not.
*/
"enable_font_subsetting" => true,

設定を変更した結果、先ほど4.5MBもあったファイルサイズが8KBのサイズまで小さくなりました。

まとめ

Laravel環境で日本語のPDFを作成するためには、laravel-dompdfパッケージのインストールと日本語化設定が必要なことがわかりました。手順的にも複雑なものではないので、ぜひLaravelでアプリケーションを構築した場合は、PDF機能の実装を行ってみてください。

PDFの作成は別のパッケージを利用しても行うことができます。