PHPでPDFを作成する時はwkhtmltopdf + snappyで戦え

# ！！最新情報は以下の記事を参照して下さい！！
[PHPでPDFを作成するときはphpwkhtmltopdfで戦え [2016年度版]](http://qiita.com/morisuke/items/88010efca9fc03466c7f)

# HTMLをPDFに変換するアプローチのつらみ
・インラインのCSSしか受け付けない
・そもそもCSS2.0系のプロパティしか受け付けない
・セレクタで要素が絞り込めない

~~mPDF、主に君のことだ。~~

# wkhtmltopdfとsnappyで幸せになろう
## wkhtmltopdf
_http://wkhtmltopdf.org/_
__Webkit__ __html__ to __pdf__ の略。
名前からも分かるようにHTMLをWebkitで解釈してPDFに変換するGoogle謹製のツールです。
もちろん、__HTML5 も CSS3.0 も難なく解釈します__。
最高感ある。

## knplabs/knp-snappy
_https://packagist.org/packages/knplabs/knp-snappy_
wkhtmltopdfをPHPで扱うためのラッパークラスです。
packagistで配布されています。

# 導入方法
CentOS 6.5 (64bit版) を想定しています。
他の環境の場合は必要なバージョンが異なるので、[本家サイト](http://wkhtmltopdf.org/downloads.html)から適切なwkhtmltopdfパッケージを入手しましょう。

## wkhtmltopdfのインストール
まずはwkhtmltopdfのインストールから進めていきます。
```rpm -ivh``` 実行時にエラーが発生した場合は、エラーを見ながらyumで足りないパッケージを入れましょう。

```bash
$ cd /usr/local/src
$ wget http://download.gna.org/wkhtmltopdf/0.12/0.12.2.1/wkhtmltox-0.12.2.1_linux-centos6-amd64.rpm
$ rpm -ivh wkhtmltox-0.12.2.1_linux-centos6-amd64.rpm
```

## 日本語フォントのインストール
wkhtmltopdfには日本語フォントが入っていないので、日本語を通すとその部分だけが真っ白になります。
なので必ず日本語フォントを別途インストールしましょう。
今回はIPAフォントのお世話になることにします。
_http://ipafont.ipa.go.jp/ipaexfont/download.html_


```bash
$ wget http://ipafont.ipa.go.jp/ipaexfont/ipaexm00201.php
$ unzip ipaexm00201.php
$ mv ipaexm00201/ /usr/share/fonts
```

## snappyの導入
composerで持ってきます。
導入したいPHPのプロジェクトで以下のコマンドを実行してください。
```composer require knplabs/knp-snappy```

# PDFの出力サンプル
HTMLを用意してSnappyの```getOutputFromHtml```メソッドに投げるだけです。
Smartyなどのテンプレートエンジンと組み合わせると、サクサクと帳票のたぐいを組んでいけると思います。

```php:sample
require './vendor/autoload.php';

$html = <<<EOF
<style>
.red {
    color:red;
    background-color: black;
    font-size:30px;
}
.opacity {
    opacity: 0.3;
}
</style>

<div class="red">
    <p>祝ってやる</p>
    <p>祝ってやる</p>
    <p>祝ってやる</p>
    <p>祝ってやる</p>
    <p class="opacity">祝ってやる</p>
    <p>祝ってやる</p>
    <p>祝ってやる</p>
    <p>祝ってやる</p>
    <p class="opacity">祝ってやる</p>
    <p>祝ってやる</p>
    <p>祝ってやる</p>
</div>
EOF;

// wkhtmltopdfの位置をコンストラクタに渡す
$pdf = new Knp\Snappy\Pdf('/usr/local/bin/wkhtmltopdf');

// encoding = utf-8をセット
$pdf->setOption('encoding', 'utf-8');

// PDFをブラウザに出力
header("Content-Type: application/pdf");
echo $pdf->getOutputFromHtml($html);
```

![test.php.png](https://qiita-image-store.s3.amazonaws.com/0/33480/ceed058c-f8cb-1ec6-bc0d-38ca86a0c4c0.png)

CSS3のプロパティであるopacityも正しく解釈されていることが分かると思います。

# 拡張してもうちょい便利に
```php:pdf.php
class Pdf extends \Knp\Snappy\Pdf
{
    // 初期値にwkhtmltopdfの位置を登録、エンコード設定をUTF-8に変更
    public function __construct($binary = '/usr/local/bin/wkhtmltopdf', array $options = [], array $env = null)
    {
        parent::__construct($binary, $options, $env);
        $this->setOption('encoding', 'utf-8');
    }

    // headerの出力も自動で行う
    public function output($html)
    {
        header("Content-Type: application/pdf");
        return $this->getOutputFromHtml($html);
    }
}
```

```php:example
echo (new Pdf)->output($html);
```


# 使用上の注意点
_https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1524_
wkhtmltopdfはテーブルを使用すると、2ページ目以降にも自動でヘッダを付与してくれるのですが、それが凄い勢いでズレたり次の列と被ったりします。
こちらのスタイルを付与すると解決できます。

```css
tr {
    page-break-inside: avoid;
}
```

# まとめ
割とどんな書き方しても解釈してくれるんでもうPDFなんて怖くありません。
PDF出力機能のチケットを切られて他の人へたらい回しにするのはもうやめましょう。
もうやめましょう（念押し）