PHPでPDFに文言の埋め込みをする方法を試す

# はじめに

PDFを作成する方法の1つとして、以下の方法を試してみました。

- ひな形PDFを用意する
- 空欄に文言を埋め込んで最終形のPDFにする

サンプルとして中央区の申請書を利用しています。

https://www.city.chuo.lg.jp/smph/kurasi/sinsei.html

↑から取得したPDFがこちら。
このPDFの空欄に文言を埋め込みました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273897/626772f7-8e51-a6ef-641b-f52ac04a58fe.png)

# 前提事項

- 環境
    - Windows 10
    - PHP 7.4.28
    - Composer 2.4.4

# 成果物

完成したものがこちら。ソースは詳細の方を参照ください。
ひな形のPDFに赤字で文言を埋め込むことができました。

- 良い点
    - 空欄に文言を埋め込むだけで良いのは楽
    - レイアウトと中身が分離できる＝分担しやすい
    - 作成速度は速い
- 悪い点
    - 位置合わせが大変
    - フォントサイズの調整が大変

↑個人的な感想です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273897/58dd973c-4bb5-ef11-cc00-a47d16f55b3f.png)

# 詳細

作成の経過を以下に記載しておきます。

## 方式検討

下記の参考サイトをもとに
・TCPDF
・FPDI
の2つのライブラリを利用してPDFを作成することにしました。

https://hsmt-web.com/blog/php-pdf-output/

https://akizora.tech/tcpdf-composer-pdffile-382

https://wakka-inc.com/blog/1000/

そのままですが、手順としてはこれだけです。
①FPDIでひな形のPDFを読み込む
②横(x)と縦(y)の位置を指定して文言を埋め込む
③結果のPDFを画面に出力する

## 準備

作業ディレクトリを作成し、composerで2つのライブラリを取得。

### TCPDFを取得する

```composer require tecnickcom/tcpdf```

```winbatch
C:\donraq\php-sample-pdf>composer require tecnickcom/tcpdf
Info from https://repo.packagist.org: #StandWithUkraine
Using version ^6.6 for tecnickcom/tcpdf
./composer.json has been created
Running composer update tecnickcom/tcpdf
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking tecnickcom/tcpdf (6.6.0)

...途中省略

Generating autoload files
1 package you are using is looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found       
```

### FPDIを取得する

```composer require setasign/fpdi```

```winbatch
C:\donraq\php-sample-pdf>composer require setasign/fpdi   
Using version ^2.3 for setasign/fpdi
./composer.json has been updated
Running composer update setasign/fpdi
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking setasign/fpdi (v2.3.6)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing setasign/fpdi (v2.3.6): Extracting archive
1 package suggestions were added by new dependencies, use `composer suggest` to see details.Generating autoload files
2 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found
```

### 取得後の状態を確認する

```winbatch
C:\donraq\php-sample-pdf>tree   
Folder PATH listing for volume OS
Volume serial number is 4EB4-CF59
C:.
└───vendor
    ├───composer
    ├───setasign
    │   └───fpdi
    │       └───src
    │           ├───PdfParser
    │           │   ├───CrossReference
    │           │   ├───Filter
    │           │   └───Type
    │           ├───PdfReader
    │           │   └───DataStructure
    │           ├───Tcpdf
    │           └───Tfpdf
    └───tecnickcom
        └───tcpdf
            ├───config
            ├───examples
            │   ├───barcodes
            │   ├───config
            │   ├───data
            │   │   └───cert
            │   ├───images
            │   └───lang
            ├───fonts
            │   ├───ae_fonts_2.0
            │   ├───dejavu-fonts-ttf-2.33
            │   ├───dejavu-fonts-ttf-2.34
            │   ├───freefont-20100919
            │   └───freefont-20120503
            ├───include
            │   └───barcodes
            └───tools
```

### ひな形PDFを配置する

```winbatch
C:\donraq\php-sample-pdf>dir  
 Volume in drive C is OS
 Volume Serial Number is 4EB4-CF59

 Directory of C:\donraq\php-sample-pdf

2022/12/11  22:23    <DIR>          .
2022/12/11  22:23    <DIR>          ..
2022/12/11  22:27                95 composer.json
2022/12/11  22:27             6,255 composer.lock
2022/12/11  10:54           118,025 jyuuminhyounihonnjin.pdf    ★これ
2022/12/11  22:27    <DIR>          vendor
               3 File(s)        124,375 bytes
```

## ひな形PDFを読み込んで表示してみる

ソースがこちら。

```php
<?php
require_once('./vendor/autoload.php');

function outputPDF($path_tmpl_pdf) {

    $fpdi = new setasign\Fpdi\Tcpdf\Fpdi();

    // ひな形PDFの1ページ目を取り込む
    $fpdi->setSourceFile($path_tmpl_pdf);
    $tpl = $fpdi->importPage(1);

    // 取り込んだひな形をPDFに反映
    $fpdi->setPrintHeader(false);
    $fpdi->AddPage();
    $fpdi->useTemplate($tpl);

    // PDFを画面に出力
    $fpdi->Output("output.pdf", "I");
}

$path_tmpl_pdf = "/donraq/php-sample-pdf/jyuuminhyounihonnjin.pdf";
outputPDF($path_tmpl_pdf);
```

簡易サーバを立ち上げて。。。

```php -S localhost:8030```

ブラウザで表示した結果がこちら。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273897/11831c9f-0c66-3280-2ef0-24273f403f41.png)

## 文言を埋め込む

文言の埋め込み位置の指定が横(x)と縦(y)の指定なので、結構面倒。
ここは位置を微調整していくしかない。

位置決めのガイドとして座標を全面に配置。
例）15-1 = x:150 y:10 という意味。

フォントは以下の2つが使用可能。
・kozgopromedium
・kozminproregular
※別途フォントのデータを組み込めば他のフォントを使うことも可能

ガイドを参考にして、いくつかの文言を配置したソースがこちら。

```php
<?php
require_once('./vendor/autoload.php');

function outputPDF($path_tmpl_pdf) {

    $fpdi = new setasign\Fpdi\Tcpdf\Fpdi();

    // ひな形PDFの1ページ目を取り込む
    $fpdi->setSourceFile($path_tmpl_pdf);
    $tpl = $fpdi->importPage(1);

    // 取り込んだひな形をPDFに反映
    $fpdi->setPrintHeader(false);
    $fpdi->AddPage();
    $fpdi->useTemplate($tpl);

    // フォントを指定　※日本語表示するためには指定が必須
    $fpdi->SetFont('kozgopromedium', '', 12);
    $fpdi->setTextColor(255, 0, 0); // 色はわかりやすいように赤
    // 住所
    $fpdi->Text(60, 35, "○○○○○○町 100-1");
    // 氏名
    $fpdi->Text(40, 45, "シナガワ　タロウ");
    $fpdi->Text(40, 51, "品川　太郎");

    // 位置決め用の座標を表示
    $fpdi->SetFont('kozgopromedium', '', 7);
    $fpdi->setTextColor(255, 160, 160);
    for ($x = 0; $x <= 20; $x++) {
        for ($y = 0; $y <= 27; $y++) {
            $fpdi->Text($x * 10, $y * 10, "$x-$y");
        }
    }

    // PDFを画面に出力
    $fpdi->Output("output.pdf", "I");
}

$path_tmpl_pdf = "/donraq/php-sample-pdf/jyuuminhyounihonnjin.pdf";
outputPDF($path_tmpl_pdf);
```

ブラウザで表示した結果がこちら。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273897/ca51ce0b-7127-87ef-2bfa-c92de3109727.png)

## 埋め込み完了

埋め込み情報をパラメータで渡すように変更。
本人が住民票の写しを1通、目的は運転免許証でとるという設定で埋め込み。

```php
<?php
require_once('./vendor/autoload.php');

function outputEmbededPDF($path_tmpl_pdf, $embed_items) {

    $fpdi = new setasign\Fpdi\Tcpdf\Fpdi();

    // ひな形PDFの1ページ目を取り込む
    $fpdi->setSourceFile($path_tmpl_pdf);
    $tpl = $fpdi->importPage(1);

    // 取り込んだひな形をPDFに反映
    $fpdi->setPrintHeader(false);
    $fpdi->AddPage();
    $fpdi->useTemplate($tpl);

    // フォントを指定
    $fpdi->SetFont('kozgopromedium', '', 12);
    $fpdi->setTextColor(255, 0, 0); // 色はわかりやすいように赤

    // 項目の埋め込み
    foreach ($embed_items as $key => $value) {
        $pos = explode(",", $key);
        $fpdi->Text($pos[0], $pos[1], $value);
    }

    // // 位置決め用の座標を表示
    // $fpdi->SetFont('kozgopromedium', '', 7);
    // $fpdi->setTextColor(255, 160, 160);
    // for ($x = 0; $x <= 20; $x++) {
    //     for ($y = 0; $y <= 27; $y++) {
    //         $fpdi->Text($x * 10, $y * 10, "$x-$y");
    //     }
    // }

    // PDFを画面に出力
    $fpdi->Output("output.pdf", "I");
}

$path_tmpl_pdf = "/donraq/php-sample-pdf/jyuuminhyounihonnjin.pdf";
$embed_items = [
    "150,26" => "2022",
    "167,26" => "12",
    "178,26" => "12",
    "60,35" => "○○○○○○町 100-1",
    "40,45" => "シナガワ　タロウ",
    "40,51" => "品川　太郎",
    "138,51" => "1900",
    "158,51" => "01",
    "172,51" => "01",
    "37,62" => "✓",
    "102,59" => "1",
    "16,119" => "✓",
    "16,177" => "✓",
    "14,212" => "✓",
];
outputEmbededPDF($path_tmpl_pdf, $embed_items);
```

ブラウザで表示した結果がこちら。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273897/a5fb1f0e-df52-8380-f859-cf3a67aa809f.png)

以上で完了。