PHPでPDFを作成するphpwkhtmltopdfはまだまだ戦える

PHPでPDFを作成するときは、長らく「PHPでPDFを作成するときはphpwkhtmltopdfで戦え [2016年度版]」にお世話になってきました。

qiita.com

久しぶりにPDFを生成する機会があったのでやってみたのですが、だいぶ新しくなっていたので、そのままでは動きませんでした。

そこで、自分がやった手順を記録として残しておきたいと思います。サーバーはCentOS7です。

wkhtmltopdfのインストール

wkhtmltopdfの本体のインストールは、以下のGistが参考になります。

How to Setup wkhtmltopdf on CentOS 7 · GitHub

ただ、Gistの「Install wkhtmltopdf」に記載されているのダウンロード URLは現在では無効です。そこで、以下のようにインストールします。

# 必要なライブラリをインストールします
yum install fontconfig libXrender libXext xorg-x11-fonts-Type1 xorg-x11-fonts-75dpi freetype libpng zlib libjpeg-turbo

# RPMパッケージをインストールします
wget https://downloads.wkhtmltopdf.org/0.12/0.12.5/wkhtmltox-0.12.5-1.centos7.x86_64.rpm
rpm -Uvh wkhtmltox-0.12.5-1.centos7.x86_64.rpm

ダウンロードURLは、素直に公式のダウンロードリストから拝借しました。

https://wkhtmltopdf.org/downloads.html

ちなみに、いきなりRPMパッケージをインストールしようとしたら怒られました。各種ライブラリは必須のようです。

[root@localhost tmp]# rpm -ivh wkhtmltox-0.12.5-1.centos6.x86_64.rpm 
error: Failed dependencies:
    fontconfig is needed by wkhtmltox-1:0.12.5-1.centos6.x86_64
    freetype is needed by wkhtmltox-1:0.12.5-1.centos6.x86_64
    libXext is needed by wkhtmltox-1:0.12.5-1.centos6.x86_64
    libXrender is needed by wkhtmltox-1:0.12.5-1.centos6.x86_64
    xorg-x11-fonts-75dpi is needed by wkhtmltox-1:0.12.5-1.centos6.x86_64
    xorg-x11-fonts-Type1 is needed by wkhtmltox-1:0.12.5-1.centos6.x86_64

wkhtmltopdfのパス

インストールされた「wkhtmltopdf」は、以下のパスにあります。

[root@localhost html]# which wkhtmltopdf
/usr/local/bin/wkhtmltopdf

日本語フォントのインストール

日本語フォントのインストール手順は「PHPでPDFを作成するときはphpwkhtmltopdfで戦え [2016年度版]」と同じです。

# IPAexfontを使用する
wget http://dl.ipafont.ipa.go.jp/IPAexfont/IPAexfont00301.zip

unzip IPAexfont00301.zip
mv IPAexfont00301 /usr/share/fonts

composer

composer.jsonを書いて、素直にphp composer.phar installします。

{
    "require": {
        "mikehaertl/phpwkhtmltopdf": "2.3.1"
    }
}

なお、使用しているライブラリは「mikehaertl/phpwkhtmltopdf」です。

github.com

動作確認用のPHPファイル

動作確認のため、少しだけPDFの出力サンプルを書き換えました。具体的には、バイナリのパスを変更しています。

  • 旧パス: /usr/local/bin/wkhtmltox/bin/wkhtmltopdf
  • 新パス: /usr/local/bin/wkhtmltopdf
<?php
require './vendor/autoload.php';

$html = <<<EOF
<!DOCTYPE html>
<html>
    <style>
    body {
        padding: 7px;
        background-color: black;
    }
    .red {
        color: red;
        font-size: 50px;
    }
    .opacity {
        opacity: 0.3;
    }
    </style>

    <body>
        <div class="red">
            <p>PDF化のテストです。</p>
            <p>あいうえお</p>
        </div>
    </body>
</html>
EOF;

use mikehaertl\wkhtmlto\Pdf;

$pdf = new Pdf([

     // バイナリの位置とエンコード形式
    'binary'   => '/usr/local/bin/wkhtmltopdf',
    'encoding' => 'utf-8',

    // 以下の指定があるとPDFをページ端まで利用できる
    'margin-top'    => 0,
    'margin-right'  => 0,
    'margin-bottom' => 0,
    'margin-left'   => 0,
    'no-outline',

]);

// ページを追加
$pdf->addPage($html);

// ブラウザにPDFを表示
$pdf->send();

出力結果

以下のように、ブラウザ上にPDFが出力されていれば成功です。

f:id:konosumi:20180622012829p:plain

フォントを明示的に指定したほうが良い

無事に出力されました!めでたしめでたし・・・と言いたいところですが、ここで重要な注意点があります。

上記のサンプルでは、フォントを明示的に指定していません。wkhtmltopdfでは、サーバ内にインストールされているフォントが使用されます。つまり、サーバー内にIPAex以外の日本語フォントが入っている場合は、どのフォントが使われるのか保証されなくなってしまいます。

文字フォントによっては、デザイン崩れや文字化けが発生する可能性があります。そこで、PDF化するHTMLファイル内のCSSで、フォントを明示的に指定する必要があります。

 <style>
    body {
        /* 明朝体の場合 */
        font-family: "IPAexMincho", "IPAex明朝";
        /* ゴシック体の場合 */
        font-family: "PAexGothic", "IPAexゴシック";
    }
</style>

サーバ内にどんなフォントが入っているのか

なお、サーバ内にインストールされているフォントの一覧は、以下のようにfc-listで確認することができます。インストールしたIPAexフォントが、正常に入っていれば問題ありません。

もし入っていなければ「fc-cache -f -v」などでフォントのキャッシュをクリアしてみてください。

[root@localhost html]# fc-list
/usr/share/fonts/stix/STIX-Regular.otf: STIX:style=Regular
/usr/share/X11/fonts/Type1/c0611bt_.pfb: Courier 10 Pitch:style=Bold Italic
/usr/share/X11/fonts/Type1/UTBI____.pfa: Utopia:style=Bold Italic
/usr/share/X11/fonts/Type1/c0419bt_.pfb: Courier 10 Pitch:style=Regular
/usr/share/fonts/stix/STIX-Italic.otf: STIX:style=Italic
/usr/share/fonts/stix/STIX-Bold.otf: STIX:style=Bold
/usr/share/X11/fonts/Type1/c0648bt_.pfb: Bitstream Charter:style=Regular
/usr/share/fonts/IPAexfont00301/ipaexg.ttf: IPAexGothic,IPAexゴシック:style=Regular
/usr/share/fonts/stix/STIX-BoldItalic.otf: STIX:style=Bold Italic
/usr/share/X11/fonts/Type1/cursor.pfa: Cursor:style=Regular
/usr/share/X11/fonts/Type1/UTB_____.pfa: Utopia:style=Bold
/usr/share/X11/fonts/Type1/c0583bt_.pfb: Courier 10 Pitch:style=Bold
/usr/share/fonts/IPAexfont00301/ipaexm.ttf: IPAexMincho,IPAex明朝:style=Regular
/usr/share/X11/fonts/Type1/UTI_____.pfa: Utopia:style=Italic
/usr/share/X11/fonts/Type1/c0582bt_.pfb: Courier 10 Pitch:style=Italic
/usr/share/X11/fonts/Type1/c0633bt_.pfb: Bitstream Charter:style=Bold Italic
/usr/share/X11/fonts/Type1/c0649bt_.pfb: Bitstream Charter:style=Italic
/usr/share/X11/fonts/Type1/c0632bt_.pfb: Bitstream Charter:style=Bold
/usr/share/X11/fonts/Type1/UTRG____.pfa: Utopia:style=Regular

PDFを横向きにする

PDFを横向きで表示したいときは、「 'orientation' => 'landscape'」を指定します。

f:id:konosumi:20180622021051p:plain

<?php
$pdf = new Pdf([
     // バイナリの位置とエンコード形式
    'binary'   => '/usr/local/bin/wkhtmltopdf',
    'encoding' => 'utf-8',

    // 以下の指定があるとPDFをページ端まで利用できる
    'margin-top'    => 0,
    'margin-right'  => 0,
    'margin-bottom' => 0,
    'margin-left'   => 0,
    // 横向きで表示したいとき
    'orientation' => 'landscape',

    'no-outline',
]);

参考

www.uetyi.com

さいごに

最新化してみましたが、問題なく無事に動きました。これからもしばらくは、phpwkhtmltopdfでまだまだ戦えそうです。