PHPでPDFを出力する場合、PDFlib や FPDF 、haru などさまざまなソリューションがありますが、たとえば、請求書や納品書といった、レイアウトが複雑なデザインの帳票を出力したいときには、 既存のPDFをテンプレートとして活用し、そこに必要な文字だけ配置していく ことでソースコードをシンプルに保つことができます。
既存のPDFをテンプレートとして読み込むことができ、かつ無償で活用できるライブラリとして、TCPDF と FPDI の組み合わせをご紹介します。
テンプレートとなるPDFを作成する
PDFの読み込みを行うFPDIは、有償のパーサーを別途導入しない場合、PDF 1.5以上のファイルをパースすることができません。テンプレートとなるPDFファイルは PDF 1.4以下の圧縮形式で作成する必要があります。
また、PHP上から文字を配置する場合、座標を使用するため(左から10mm、上から20mmの位置から…といった具合)、Illustratorなどのソフトを使用したほうが効率的です。
たとえば、上の例ではIllustratorを使用して領収書のひな形を作成し、ドキュメント上に X : 42mm / Y : 108mm の位置に 幅 : 56mm × 高さ : 10mm のグレーのボックスを配置しています。ここにPHPを使って宛名を差し込んでいきます。
IllustratorからPDF 1.4互換のファイルを作成する
Illustrator CCの場合、「ファイルの種類」で「Adobe PDF」を選択し、続いて表示されるダイアログ上の、「互換性のある形式」で「Acrobat 5(PDF 1.4)」を選択します。
ライブラリをダウンロードする
TCPDF
- TCPDFをダウンロードします。ドキュメントなどが必要でなければ tcpdf_min_* を選択すればよいでしょう。
- ダウンロードしたファイルは解凍して、PHPのinclude_path上に
tcpdf
というフォルダ名で配置しました。Symfony2で使用する場合は、libフォルダなどを作成し、autoload.phpに以下のように追記します。
$loader = require __DIR__.'/../vendor/autoload.php';
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
// include_pathを追加する
set_include_path(get_include_path() . PATH_SEPARATOR . __DIR__ . '/../lib');
return $loader;
フォント
- 日本語のフォントを使用したいので、今回は MigMixフォント を使用させてもらいます。MigMix 2Pをダウンロードしたら、解凍して
migmix-2p-bold.ttf
とmigmix-2p-regular.ttf
をtcpdf/fonts/
フォルダに配置します。 -
tcpdf/fonts/
フォルダにはPHP実行ユーザに書き込み権限が必要ですので、パーミッションを変更しておきましょう。
FPDI
- FPDIをダウンロードします。
- ダウンロードしたファイルは解凍して、TCPDFを配置した
tcpdf
フォルダ内に配置しましょう。この時点でtcpdf
フォルダ内は以下のような配置になっているはずです。
lib/
tcpdf/
fonts/
migmix-2p-bold.ttf
migmix-2p-regular.ttf
fpdi.php
…(ほか、FPDIのファイル群)
tcpdf.php
…(ほか、TCPDFのファイル群)
ライブラリを使用して、PDFを出力する
準備はここまでです。
あとは、PHPからテンプレートとなるPDFを読み込み、文字列を追加して出力します。
以下はSymfony2のコントローラですが、もちろんほかのフレームワークでも同様の書き方でPDFを出力可能かと思います。
<?php
namespace Awesome\DemoBundle\Controller;
// include_pathからTCPDFとFPDIを読み込む
require_once('tcpdf/tcpdf.php');
require_once('tcpdf/fpdi.php');
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class DeliveriesPdfController extends Controller
{
public function listAction(Request $request)
{
$receipt = new \FPDI();
// PDFの余白(上左右)を設定
$receipt->SetMargins(0, 0, 0);
// ヘッダーの出力を無効化
$receipt->setPrintHeader(false);
// フッターの出力を無効化
$receipt->setPrintFooter(false);
// フォントを登録
$fontPathRegular = $this->getLibPath() . '/tcpdf/fonts/migmix-2p-regular.ttf';
$regularFont = $receipt->addTTFfont($fontPathRegular, '', '', 32);
$fontPathBold = $this->getLibPath() . '/tcpdf/fonts/migmix-2p-bold.ttf';
$boldFont = $receipt->addTTFfont($fontPathBold, '', '', 32);
// ページを追加
$receipt->AddPage();
// テンプレートを読み込み
$receipt->setSourceFile($this->getLibPath() . '/tcpdf/tpl/receipt.pdf');
// 読み込んだPDFの1ページ目のインデックスを取得
$tplIdx = $receipt->importPage(1);
// 読み込んだPDFの1ページ目をテンプレートとして使用
$receipt->useTemplate($tplIdx, null, null, null, null, true);
// 書き込む文字列のフォントを指定
$receipt->SetFont($regularFont, '', 11);
// 書き込む文字列の文字色を指定
$receipt->SetTextColor(255, 0, 0);
// X : 42mm / Y : 108mm の位置に
$receipt->SetXY(42, 108);
// 文字列を書き込む
$receipt->Write(0, '山田 太郎');
$response = new Response(
// Output関数の第一引数にはファイル名、第二引数には出力タイプを指定する
// 今回は文字列で返してほしいので、ファイル名はnull、出力タイプは S = String を選択する
$receipt->Output(null, 'S'),
200,
array('content-type' => 'application/pdf')
);
// レスポンスヘッダーにContent-Dispositionをセットし、ファイル名をreceipt.pdfに指定
$response->headers->set('Content-Disposition', 'attachment; filename="receipt.pdf"');
return $response;
}
/**
* @return string
*/
private function getLibPath()
{
return realpath(sprintf('%s/../lib', $this->get('kernel')->getRootDir()));
}
}
これで、文字列が追加されたPDFが得られます。
もちろんこのまま $receipt->AddPage();
を続ければ、領収書をまとめてPDFとして出力することもできます。
以下のページを参考にさせていただきました :
TCPDFとFPDIの使い方メモ