LoginSignup
352

More than 5 years have passed since last update.

PHPでPDF帳票を出力する方法(TCPDF + FPDI)

Last updated at Posted at 2014-11-17

PHPでPDFを出力する場合、PDFlibFPDFharu などさまざまなソリューションがありますが、たとえば、請求書や納品書といった、レイアウトが複雑なデザインの帳票を出力したいときには、 既存のPDFをテンプレートとして活用し、そこに必要な文字だけ配置していく ことでソースコードをシンプルに保つことができます。

既存のPDFをテンプレートとして読み込むことができ、かつ無償で活用できるライブラリとして、TCPDFFPDI の組み合わせをご紹介します。

テンプレートとなるPDFを作成する

PDFの読み込みを行うFPDIは、有償のパーサーを別途導入しない場合、PDF 1.5以上のファイルをパースすることができません。テンプレートとなるPDFファイルは PDF 1.4以下の圧縮形式で作成する必要があります。

また、PHP上から文字を配置する場合、座標を使用するため(左から10mm、上から20mmの位置から…といった具合)、Illustratorなどのソフトを使用したほうが効率的です。

ss1.jpg

たとえば、上の例ではIllustratorを使用して領収書のひな形を作成し、ドキュメント上に X : 42mm / Y : 108mm の位置に 幅 : 56mm × 高さ : 10mm のグレーのボックスを配置しています。ここにPHPを使って宛名を差し込んでいきます。

IllustratorからPDF 1.4互換のファイルを作成する

Illustrator CCの場合、「ファイルの種類」で「Adobe PDF」を選択し、続いて表示されるダイアログ上の、「互換性のある形式」で「Acrobat 5(PDF 1.4)」を選択します。

ライブラリをダウンロードする

TCPDF

  1. TCPDFをダウンロードします。ドキュメントなどが必要でなければ tcpdf_min_* を選択すればよいでしょう。
  2. ダウンロードしたファイルは解凍して、PHPのinclude_path上に tcpdf というフォルダ名で配置しました。Symfony2で使用する場合は、libフォルダなどを作成し、autoload.phpに以下のように追記します。
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;

フォント

  1. 日本語のフォントを使用したいので、今回は MigMixフォント を使用させてもらいます。MigMix 2Pをダウンロードしたら、解凍して migmix-2p-bold.ttfmigmix-2p-regular.ttftcpdf/fonts/ フォルダに配置します。
  2. tcpdf/fonts/ フォルダにはPHP実行ユーザに書き込み権限が必要ですので、パーミッションを変更しておきましょう。

FPDI

  1. FPDIをダウンロードします
  2. ダウンロードしたファイルは解凍して、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を出力可能かと思います。

PdfController.php
<?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が得られます。

ss2.jpg

もちろんこのまま $receipt->AddPage(); を続ければ、領収書をまとめてPDFとして出力することもできます。

以下のページを参考にさせていただきました :
TCPDFとFPDIの使い方メモ

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
352