Laravel8でTCPDFを使ってフォームをPDF出力の実装


## やりたいこと
TCPDF+FPDIを使って入力フォームで入力した名前などをPDFに展開する。参加証の発行に利用しました。

## ちょっとイレギュラーです
LaravelにはPDFを作成してくれるライブラリ（下記）などもありますが、既存のコードをなるべく応用したかったため。

https://codelikes.com/laravel-dompdf/

## その他の参考にしたサイト
https://hsmt-web.com/blog/php-pdf-output/#p1-3


## 前提条件

- Laravel8
- Jsetstream導入済み
- Dockerでテストしています

## 流れ
ログイン済み→viewファイル上でフォーム入力→ControllerでPDF作成→PDFが発行される

### composerでライブラリをインストール （Dockerで開いたコマンドラインの中で）

```
composer require tecnickcom/tcpdf
composer require setasign/fpdi
```

### Fontの配置

app/public/fonts/　に利用する日本語フォントを保存

### ベースのPDF
app/public/assets/pdf_template/　に基準となるPDFを保存


### 入力フォームの作成


```php:sankasyou.blade.php
<x-app-layout>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script type="text/javascript">
        $(function() {
            $('button#add').click(function() {

                var tr_form = '' +
                    '<tr>' +
                    '<td><input class="w-100" type="text" maxlength="15" name="text_name_sei[]"></td>' +
                    '<td><input class="w-100" type="text" maxlength="15" name="text_name_mei[]"></td>' +
                    '</tr>';
                $(tr_form).appendTo($('table > tbody'));
            });
        });
    </script>

    <div class="py-6">
        <div class="max-w-7xl mx-auto sm:px-4 lg:px-4">
            <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
                <div class="p-2 sm:px-20 bg-white border-b border-gray-200">
                    <div class="mt-2 text-2xl">
                        参加証システム
                    </div>
                </div>

                <div class="bg-gray-200 bg-opacity-25 grid grid-cols-1 md:grid-cols-1">
                    <div class="p-6">

                        <div class="m-0">
                            <div class="mt-1 text-gray-900 rounded p-1">
                                <div class="fs-4">参加証に記載するお名前を入力してください</div>

                                <form action="{{ route('pdf_export') }}" method="post" enctype="multipart/form-data">
                                    {{-- formに必用 --}}
                                    {{ csrf_field() }}

                                    <table class="table table-striped">
                                        <thead>
                                            <tr>
                                                <th class="fs-5">姓</th>
                                                <th class="fs-5">名</th>
                                            </tr>
                                        </thead>
                                        <tbody>
                                            <tr>
                                                <td><input class="w-100" type="text" maxlength="15" name="text_name_sei[]"></td>
                                                <td><input class="w-100" type="text" maxlength="15" name="text_name_mei[]"></td>
                                            </tr>
                                        </tbody>
                                        <tfoot>
                                            <tr>
                                                <td>
                                                    <button id="add" type="button"
                                                        class="btn btn-secondary btn-sm bg-secondary">名前入力欄を追加する</button>
                                                </td>
                                            </tr>
                                        </tfoot>
                                    </table>

                                    <label for="bcertificat_date" class="form-label">参加証発行日付 （2022年9月10日の場合は 2022/09/10 と入力してください）</label>
                                    <div class="input-group mb-4">
                                        {{-- 発行日付の入力 --}}
                                        
                                        <input class="input-group-text" type="date" name="date" id="certificat_date">
                                    </div>

                                    <label for="dantai" class="form-label">団体名の入力</label>
                                    <div class="input-group mb-4">
                                        <input type="text" name="text_dantai" size="50"
                                            value="○○愛好会" id="dantai">
                                    </div>
                                    <div class="input-group mb-3 float-end">
                                        <button class="btn btn-warning bg-warning" type="submit">参加証作成</button>
                                    </div>

                                </form>
                                
                              </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
</x-app-layout>
```
まずい部分を抜いて書いてあるのでもしかすると動かないかもしれません。

route('pdf_export')にPOSTすると、Controllerを叩いてPDFが発行されます。


### Controllerの作成

`php artisan make:controller PdfController`


### PdfControllerの中身

```php:PdfController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use setasign\Fpdi\Tcpdf\Fpdi;
use TCPDF_FONTS;

class PdfController extends Controller
{

    public function pdf_export(Request $request)
    {
        $pdf = new Fpdi(); //参考ページとは異なり最近はこう書くらしい

        #formの内容を変数に
        $namelist_sei = $request["text_name_sei"];
        $namelist_mei = $request["text_name_mei"]; 
        $date = $request["date"];
        $date = str_replace('-', '　　', $date);

        $dantai = $request["text_dantai"];
        
        $namelist = $request["text_name_sei"]; 

        for ($i = 0; $i < count($namelist_sei); $i++) {
            $namelist[$i] = $namelist_sei[$i] . "　" . $namelist_mei[$i];
        }

        // フォントを設定
        $tcpdf_fonts = new TCPDF_FONTS();
        $font = $tcpdf_fonts->addTTFfont(public_path('fonts/フォントのファイル名.ttf'));

        // PDFの作成

        foreach($namelist as $value){

            $pdf->setPrintHeader(false);
            $pdf->setPrintFooter(false);
            $pdf->SetFont($font, '', 15);//この書き方を知らずに1時間くらい悩んだ

            $pdf->AddPage();
            $pdf->setSourceFile(public_path('assets/pdf_template/base.pdf'));
            $tpl = $pdf->importPage(1);
            $pdf->useTemplate($tpl);

            #名前の入力（位置などは適当です）
            $pdf->SetX(10);
            $pdf->Write(75, htmlspecialchars($value), "", false,);

            #日付の入力（位置などは適当です）
            $pdf->SetX(10);

            $pdf->Write(141, htmlspecialchars($date), "", false,);

            #団体名の入力（位置などは適当です）
            $pdf->Text(10, 10, htmlspecialchars($dantai));
        }

        //$pdf->Output(出力時のファイル名, 出力モード);
        $pdf->Output("sankasyou.pdf", "I");
    }
}

```


### ルート設定
web.phpにルートを追加します。


```php:web.php
use App\Http\Controllers\PdfController;

//入力ページは認証つきにする
Route::middleware(['auth:sanctum', 'verified'])->get('sankasyou', function () {
    return view('sankasyou');
})->name('certificate');

//POST先の設定
Route::post('pdf_export', [PdfController::class, 'pdf_export'])->name('pdf_export');

```

これでPDFが出力されます。
ControlleでPDFが出るという仕組みは面白いですね。

### 参考にしたサイト
https://tech.ilovex.co.jp/tech-blog/article-7-tcpdf-fpdi-laravel-pdf