😉

Laravel超初心者がMpdfでpdfを生成するまで

2023/05/02に公開

20230726追記:カスタムフォントをあてる続編あります。

https://zenn.dev/chromel/articles/d60134129a8a42

前振り

こんにちはクロメルです。最近Laravelを始めました。
仕事でPHPで行うTCPDFでPDFを生成していましたがなかなか不自由だったので、もっと自由に組めるというLaravelのMpdfに移行しようと試作してみました。このライブラリは情報が少ないです。また、もっと有名なdompdfがあるのでmpdfの検索で、有名なそっちに行き当たりがちです。もうネイティブPHPからは足を洗うべきかな。今回は超初心者向けにめっちゃ基礎からやります。

最初に生成しておくコマンド

今回のプロジェクト名はPdfにしておきます。
PowerShellで開発フォルダ("artisan"って拡張子無しのファイルがあるフォルダ)に行った後、次を打ちましょう!

composer require carlos-meneses/laravel-mpdf
php artisan make:controller PdfController
php artisan make:model Pdf -m

Route

まずはRouteの設定です。今回は表示なのでgetメソッドです。これを表示するURLが/pdfで、後述のPdfContoroller内の使用する関数名がviewPdfって訳です。

route/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PdfController;

Route::get('/pdf', [PdfController::class,'viewPdf'])->name('viewPdf');

Controller

次にコントローラの設定です。最初のartisanで作ったので、/app/Http/Controllers/PdfController.phpは中身が空ですがもうできていると思います。次のように書きましょう。

PdfController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use PDF; //ここお忘れなく

class PdfController extends Controller
{
    public function viewPdf()
    {
        $data = [
            'foo' => 'bar'
        ];
	//ここでviewに$dataを送っているけど、
	//今回$dataはviewで使わない
        $pdf = PDF::loadView('pdf.document', $data);

        return $pdf->stream('document.pdf'); //生成されるファイル名
    }
}

注意する点は、Route内で書いたクラス名PdfControllerと関数名viewPdfを同一にして対応させることです。また、PDF::loadView('pdf.document', $data);'pdf.document'に関しては、viewファイル/resource/views/pdf/document.blade.phpの最後のpdf/document.blade.phpに対応しています。この'pdf.document'にしないとエラーになります。

Config

次はconfigファイルです。/config/app.phpを開きましょう。ここの所に次を書き足します。

app.php
'providers' => [
Mccarlosen\LaravelMpdf\LaravelMpdfServiceProvider::class,
],
'aliases' => Facade::defaultAliases()->merge([
// 'ExampleClass' => App\Example\ExampleClass::class,
'PDF' => Mccarlosen\LaravelMpdf\Facades\LaravelMpdf::class,
])->toArray(),

そして、次をPowerShellで打ちましょう。
これは下記の本家リンクでみると、下で行うconfig/pdf.phpを作るだけでこれを行わなくてもよさそうですが、正直よくわかりません汗

php artisan vendor:publish --tag=mpdf-config

Model

これは最初のartisanコマンドで作られていて、改変の必要はありません。/app/Models/Pdf.phpですね。

View

これは、どうやらHTML形式でじかに書くようです。
使えるタグと使えないものがあるようなので、いろいろやってみてください。便利ですね!/resource/views/pdf/document.blade.phpを作りましょう。コントローラのPDF::loadView('pdf.document', $data);pdf.documentと対応させることを忘れずに!例えば、こうしましょう。

document.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
#header{
    width:720px;
    height:100px;
    background-color: #aaa;
}
</style>
</head>
<body>
Hello World!!こんにちは!
<div id="header"></div>
</body>
</html>

多分、cssを直書きはよろしくないかもですが。。。
今後、外部css読み込み法が分かったら改訂したいです。

日本語化

これもなかなか悩みました。configで設定します。
configを設定するには任意の名前.phpをconfigフォルダに入れておけばよいです。例えば、下に示す感じでオーケー。

config/pdf.php
<?php

use Illuminate\Support\Facades\Facade;
return [
    'mode'                 => '',
    'format'               => 'A4',
    'default_font_size'    => '12',
    'default_font'         => 'sans-serif',
    'margin_left'          => 10,
    'margin_right'         => 10,
    'margin_top'           => 10,
    'margin_bottom'        => 10,
    'margin_header'        => 0,
    'margin_footer'        => 0,
    'orientation'          => 'P',
    'title'                => 'Laravel mPDF',
    'author'               => '',
    'watermark'            => '',
    'show_watermark'       => false,
    'watermark_font'       => 'sans-serif',
    'display_mode'         => 'fullpage',
    'watermark_text_alpha' => 0.1,
    'auto_language_detection'  => true,
    'temp_dir'               => rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR),
    'pdfa'          => false,
    'pdfaauto'      => false,
    'custom_font_dir' => base_path('resources/fonts/'),
    'custom_font_data' => [
        'ipag' => [
        'R'  => 'ipag.ttf',
        ],
    ],
];

日本語化で大事なのは'auto_language_detection' => true,であることです。僕はこれを設定する方法以外はまだ模索中です。そもそも外部cssの適用もできていないのです汗
一つ言うべきことがあるとすれば、configファイルは一通り英語を読んで、大体何をしているかを把握した方がよさそうですね。

ご本家様へのリンク
https://github.com/mccarlosen/laravel-mpdf

こちら参考にさせていただきました
https://qiita.com/yukieeeee/items/2085aad47f73aae3889e

今日はここまで!お疲れさまでした!

Discussion