FuelPHPとTCPDFで日本語PDFを作成する正しい方法

FuelPHP

どうも、Fuelの開発ペースに不安を覚え、Laravelへの移行を検討しているもとやんです。
まぁFuelはフットプリントが小さいことと全体の見通しが良いのでそういう意味ではいまだに気に入ってるんですけど。

Laravelは大体がより今風でいいんですけど、一番イヤーなところはクラス構成をあまりFWが強制してこないので、どこに何を置くのがベストプラクティスなのかがパッと見イマイチわからない点。
ユーザに対して自由度を与えているといえばその通りですが、縛ってくれるFWのほうが私は考えることが減って好みです。

TCPDF+FuelPHP?

「fuelphp tcpdf」でググればいくらでも参考情報が出てくるんですが、一部古くなっているところがあって、最新にアジャストしたのでメモしておきます。
ググったときにたぶん1位に出てくるのは

FuelPHP の fuel-pdf パッケージを利用し日本語の PDF を生成する

です。
で、導入すべきライブラリとしては
https://github.com/fuel-packages/fuel-pdf
を推しています。まぁoilのpackageコマンドで入れられるので悪くはないです。

php oil install pdf

修正点1 Packageのリネーム

するとpackageディレクトリ内にfuel-pdfという名前でフォルダができます。
ライブラリ内のコードがpdfっていうフォルダ名でインストールされることを期待してハードコーディングされているので、リネームしておきましょう。まずこれが修正点その1.

IPAフォントをインストールする

TCPDFに標準で入っている日本語フォントだとちょっとお粗末なので、「IPAフォント」をインストールします。
インストールしたパッケージ内のtcpdfにはttfファイルをtcpdfで使えるようにするためのツール「makeallttffonts.php」と「ttf2ufm」が入っていますが、これが完全には動作しません。

php makeallttffonts.php ipaexg.otf ipaexg.ufm

こんな感じで変換をかけると、

Warning: glyph IDC2ff3 needs hint stack depth 133
  (limit 128): removed the substituted hints from it

こんな感じのエラーが大量に出ます。
そしてその結果出力した日本語ファイルに含まれるフォントが歯抜け状態になり、いくつかの文字が空白で表示される状態になってしまいます。

修正点2 最新のTCPDFを使う

対応方法としては、パッケージに同梱のものではなく、最新のTCPDFを別途ダウンロードしてきて使うことです。
toolsフォルダには「tcpdf_addfont.php」という新しいツールが入っているので、これを使いましょう。

php tcpdf_addfont.php -b -t TrueTypeUnicode -i ipaexg.ttf

するとfontsファイル内に必要なファイルが変換して出力されますし、こちらはしっかりと文字がすべて表示されます。

パッケージの中のTCPDFを丸ごと差し替えてもいいですし(言語設定ファイルは移植する必要がありましたが)、変換だけ新しいバージョンで行った後にフォントファイルだけを移植しても問題なく動作しました。

以上

PHP7.2以上でエラーが出るようになった場合の対処法(2018/10/26追記)

TCPDFのバージョンを6.2.13から最新の6.2.26にアップデートしても「tcpdf_fonts.php」にて、undefined offsetエラーが出るようになり、PDFが作れなくなりました。
色々といじっていたところ、一部の記号(私の環境では全角の()や⇒)を含んだ文字列を出力しようとすると、同エラーが出るようになってしまいました。

とりあえずtcpdf_fonts.phpを以下のようにいじったらPDFが出るようにはなったのですが、意味を理解せずにいじったのでちょっとプルリクとか出しにくい・・。

tcpdf_fonts.php 2123行目

$type = TCPDF_FONT_DATA::$uni_type[$ta[$i]];  //変更前
$type = TCPDF_FONT_DATA::$uni_type[$ta[$i]]??'L';  //変更後

tcpdf_fonts.php 2477行目

if ((TCPDF_FONT_DATA::$uni_type[$chardata[$i]['char']] == 'AL') OR ($chardata[$i]['char'] == 32) OR ($chardata[$i]['char'] == 8204)) {  //変更前
if ((TCPDF_FONT_DATA::$uni_type[$chardata[$i]['char']]??null == 'AL') OR ($chardata[$i]['char'] == 32) OR ($chardata[$i]['char'] == 8204)) {  //変更後

tcpdf_fonts.php 2497行目

if (TCPDF_FONT_DATA::$uni_type[$thischar['char']]== 'AL') {  //変更前
if (TCPDF_FONT_DATA::$uni_type[$thischar['char']]??null == 'AL') {  //変更後

まぁ$uni_typeの定義の中にエラーとなる文字コードが入ってないことは確認してあるのですが、上記の記号を含んでいない場合は、エラーになる文字コードが入っていてもPDFがちゃんと出るので、マルチバイトの処理になんか問題があるんだろうなーという感じです。

コメント

タイトルとURLをコピーしました