PHPからPDFを出力(dompdf)

2016年1月15日

先日、「PHPからPDFを出力する」という内容の実装を行ったのでその際のメモです。
PHPからPDFを出力する方法はいくつかあるのですが、今回は「PHP以外のアプリケーションは利用しない」という制約があったので、いろいろ検討した結果「dompdf」というライブラリを利用することにしました。

dompdfでは、HTML + CSSにてPDFをデザインでき、多少制約はあるもののそのレイアウトでPDFを作成できるのが利点です。細かく座標指定してのレイアウトがいらないのが良いですね。ほかにも同様のことができるライブラリとして「tcpdf」というのがあったのですが、利用出来るスタイルの制約により、今回のレイアウトが組めなかったのでアウト。dompdfを利用することに決めました。

dompdfは、以下のgithubからダウンロードができます。
https://github.com/dompdf/dompdf

ダウンロードしたものに対して、私は以下のような構造で配置しました。
dompdf
 > font
 > Library
  > include
  > lib
  > www
   その他dompdfモジュール

配備したら次に日本語フォントを探します。今回はIPA(独立行政法人 情報処理推進機構)が配布しているIPAフォントのipagp.ttfを利用しました。
ipagp.ttfを上記のfontフォルダに格納し、dompdfフォルダにて以下のコマンドを叩きます。

php load_font.php ipagothic ../font/ipagp.ttf

すると以下のエラーが発生しました。

Warning: require_once([省略]/dompdf/Library/lib/php-font-lib/classes/Font.php): failed to open stream: No such file or directory in [省略]/dompdf/Library/dompdf_config.inc.php on line 332

Fatal error: require_once(): Failed opening required '[省略]/dompdf/Library/lib/php-font-lib/classes/Font.php' (include_path='.:/usr/share/pear:/home/includes') in [省略]/dompdf/Library/dompdf_config.inc.php on line 332

確認すると、libの中に「php-font-lib」というのが入っていませんでした。ネットを探して以下より「php-font-lib」をダウンロード。
https://github.com/PhenX/php-font-lib

libフォルダ内に「php-font-lib/classes」を作成し、その中にダウンロードしたものを格納しました。
再度先ほどのコマンドを叩きました。今度は以下のエラーが発生しました。

Unable to find bold face file.
Unable to find italic face file.
Unable to find bold_italic face file.
Copying ../font/ipagp.ttf to [省略]/dompdf/Library/lib/fonts/ipagp.ttf...
Generating Adobe Font Metrics for [省略]/dompdf/Library/lib/fonts/ipagp...

Fatal error: Class 'Font' not found in [省略]/dompdf/Library/load_font.php on line 141

ここで結構はまったのですが、エラーからするに「Font」が見つからないということ、いろいろ確認したところ、Fontクラスに名前空間が付いていたことを見つけました。っということで、「load_font.php」を開いて、クラスをロードしているところで、名前空間を足しました。

$font_obj = FontLib\Font::load($dest);

これで再度コマンドを実行。再びエラー。。。

Unable to find bold face file.
Unable to find italic face file.
Unable to find bold_italic face file.
Copying ../font/ipagp.ttf to [省略]/dompdf/Library/lib/fonts/ipagp.ttf...
Generating Adobe Font Metrics for [省略]/dompdf/Library/lib/fonts/ipagp...
[省略]/dompdf/Library/lib/fonts/ipagp.ttf
Fatal error: Class 'FontLib\TrueType\File' not found in [省略]/dompdf/Library/lib/php-font-lib/classes/Font.php on line 60

このエラーがなかなか厳しかった。。。いろいろ調べて行った結果以下のようにすることで回避できることがわかりました。
Library直下にある「dompdf_config.inc.php」の332行目あたり。

if (DOMPDF_ENABLE_AUTOLOAD) {
  require_once(DOMPDF_INC_DIR . "/autoload.inc.php");
  require_once(DOMPDF_LIB_DIR . "/php-font-lib/classes/Autoloader.php");
  require_once(DOMPDF_LIB_DIR . "/php-font-lib/classes/Font.php");
}

そして、再度コマンド実行!ついにエラーなく成功!

Unable to find bold face file.
Unable to find italic face file.
Unable to find bold_italic face file.
Copying ../font/ipagp.ttf to [省略]/dompdf/Library/lib/fonts/ipagp.ttf...
Generating Adobe Font Metrics for [省略]/dompdf/Library/lib/fonts/ipagp...
[省略]/dompdf/Library/lib/fonts/ipagp.ttf

では早速出力テスト。
以下にサンプルを置いておきます。
PDFのテンプレート
PDF出力サンプル

PDFのテンプレートとするHTMLファイルは上記サンプルを確認してください。試してみたところ、だいたいスタイルは適応されるのですが、一部適応されないものがあったと思います。とはいえ、dompdfの場合は「position:absolute」が使えるので大抵の配置でこまることはないでしょう。
PDFを出力するPHPソースはいたってシンプルです。

require_once('dompdf/Library/dompdf_config.inc.php');
require_once('dompdf/Library/lib/php-font-lib/classes/Autoloader.php');
require_once('dompdf/Library/lib/php-font-lib/classes/Font.php');
require_once('dompdf/Library/lib/php-font-lib/classes/BinaryStream.php');

$template = file_get_contents("pdf.html");
$pdf = new DOMPDF;
$pdf->load_html($template);
$pdf->set_option('enable_font_subsetting', true);
$pdf->render();
	
//ファイル出力の場合
//file_put_contents("test.pdf", $pdf->output());
	
//画面で確認する場合
$pdf->stream("test.pdf", array("Attachment" => 0));exit();
	
//ダウンロード場合
//$pdf->stream("test.pdf");exit();

dompdfのライブラリを読み込みます。その後、HTMLソースをfile_get_contents等で取得。
dompdfのクラスを作成し、「load_html」にてロードさせ、PDFを生成すればOKです。

ちなみに、「$pdf->set_option(‘enable_font_subsetting’, true);」の一文は非常に重要です。これを記載しないとfontファイルの内容が全てPDFに埋め込まれることになり、すごく大きなファイルになります。これの指定により、使用しているもののみが埋め込まれる形になるようです。
一応、上記コードに、ファイル出力の場合とダウンロードの場合も記載しておきました。

参考になればと思います。