Pure-PHP で PDF を作成する

## はじめに

PHP には mPDF のように HTML→PDF なライブラリがいくつかありますが、ここでは [Thinreports for PHP](https://thinreports-php.github.io) を使った別のアプローチで PDF を作成する方法を紹介します。

## Thinreports for PHP

### ざっくり言うと

  * 国産 OSS（The MIT License）
  * 0.8.0-alpha1（2015年7月時点最新）
  * Pure PHP
  * PHP 5.6 以降対応（0.8.0-alpha2 より 5.3 以降対応予定）
  * [Thinreports](http://www.thinreports.org) の PHP 版 専用 Generator

追記 at 2015.11.23:
本日、最初のメジャーリリース 0.8.0 をリリースしました。
https://github.com/thinreports-php/thinreports-php/releases/tag/0.8.0

追記 at 2015.8.10:
本日、PHP 5.3 以降に対応した 0.8.0-alpha2 がリリースされました。
https://github.com/thinreports-php/thinreports-php/releases/tag/0.8.0-alpha2

追記: 
PHP カンファレンス 2015 福岡で発表したときの資料に、この辺のことは全部書いてあるのでよろしければどうぞ。
https://speakerdeck.com/hidakatsuya/introduction-of-thinreports-for-php

### そもそも Thinreports とは

  * http://www.thinreports.org
  * 国産 OSS
  * 専用レイアウトデザイナ [Thinreports Editor](https://chrome.google.com/webstore/detail/thinreports-editor/cdlcnnandndjkbbdcbpnjoimphmifkfn) と専用 PDF 生成ライブラリが必要
  * 専用 PDF 生成ライブラリは、PHP 版の他に [Ruby 版](https://github.com/thinreports/thinreports-generator) がある
  * Thinreports Editor は Chrome アプリ

### PDF 生成までの基本的な流れ

  1. 専用デザイナ [Thinreports Editor](https://chrome.google.com/webstore/detail/thinreports-editor/cdlcnnandndjkbbdcbpnjoimphmifkfn) を使って帳票レイアウトファイルを作成
  2. レイアウト作成時に、値を埋め込みたいところに名前付きの領域（テキストボックスみたいな）を定義しておく
  3. 作成したレイアウトファイルを Thinreports for PHP で読み込んで、値を埋め込むなどして PDF を生成するコードを書く

## Hello World

実際にやってみます。Thinreports for PHP の [README.md](https://github.com/thinreports-php/thinreports-php/tree/master#quick-start) にも流れが書いてありますのでそちらも併せて参考にすると良いと思います。

### 前提

PHP5.6 と Composer がすでにインストールされていることが前提です。方法はググってください。

### 1. Thinreports Editor をインストール

Editor は Chrome アプリなので、Google Chrome をインストールしていない場合はインストールする必要があります。方法はググりましょう。

Chrome の準備ができたら [Chrome ウェブストア](https://chrome.google.com/webstore/detail/thinreports-editor/cdlcnnandndjkbbdcbpnjoimphmifkfn) （無料）にアクセスして、右上の "CHROME に追加" をクリックすると Thinreports Editor がインストールできます。このとき、 **Google アカウントは必ずしも必要ではありません。**

### 2. 帳票レイアウトファイルを作成

まず、Thinreports Editor を起動して、新規作成ボタンから新しいレポートを作成します。ここでは、用紙サイズや余白などはデフォルトのままとして OK をクリックします。

![sc1.png](https://qiita-image-store.s3.amazonaws.com/0/4232/ef6881e4-f5d6-224f-678b-050ef8ddeae8.png)

続いて、下記のようにテキストブロックを貼り付けて、フォントサイズを **48** にして、ID を **hello_world** としておきます。

![sc2.png](https://qiita-image-store.s3.amazonaws.com/0/4232/ea1a4f05-2ca1-d85b-864d-1911b67a8f16.png)

で、保存ボタンを押すと、保存先を指定するダイアログが表示されるので、作成したレイアウトファイルを任意の場所に保存します。ここではデスクトップに **hello_world** ディレクトリを作成して、その中に **layout.tlf** という名前で保存したとします。つまり **~/Desktop/hello_world/layout.tlf** に保存したことになります。

### 3. thinreports-php のインストール

下記内容で ~/Desktop/hello_world/composer.json を作成します。

```json:composer.json
{
    "require": {
        "thinreports-php/thinreports-php": "@alpha"
    }
}
```

~/Desktop/hello_world ディレクトリで下記コマンドを実行して thinreports-php をインストールします。

    $ cd ~/Desktop/hello_world
    $ composer install

### 4. PDF 生成スクリプトを書く

下記内容のスクリプトを ~/Desktop/hello_world/hello_world.php として作成します。

```php:hello_world.php
<?php
require 'vendor/autoload.php';

date_default_timezone_set('Asia/Tokyo');

$report = new Thinreports\Report('layout.tlf');

# 1st page
$page = $report->addPage();
$page->item('hello_world')->setValue('Hello World');

# 2nd page
$page = $report->addPage();
$page('hello_world')->setValue('Hello Thinreports')
                    ->setStyle('color', '#ff0000');

$report->generate('hello_world.pdf');
```

### 5. 実行する

    $ php hello_world.php

成功すると ~/Desktop/hello_world/hello_world.pdf に PDF ファイルが作成されます。

その他、本家 Thinreports の情報も含めて下記ページもどうぞ:

  * 本家 Thinreports
    * [Thinreports 公式サイト](http://www.thinreports.org)
    * [Thinreports Documentation](http://www.thinreport.org/documentation/)
    * [GitHub](https://github.com/thinreports)
  * Thinreports for PHP
    * [GitHub](https://github.com/thinreports-php)
    * [Packagist](https://packagist.org/packages/thinreports-php/thinreports-php)

## Tips

他にもいろいろできるので簡単に紹介しておきます。下記以外にも、Editor で各図形のプロパティを見たり、いじったりするとできそうなことが大体わかるんじゃないかと思います。

### 罫線や図形、テキストのスタイルを動的に操作する

テキストブロック（Hello World で使ったやつ）以外にも、罫線や図形、静的なテキストのスタイルもコードから変更できます。やり方は、まず、テキストブロックと同様、レイアウト上で図形などのオブジェクトに対して ID を設定して、下記のようにコードからその ID に対してスタイルを設定します。

```php
// なんでも
$page->item('any_object')->hide();
$page->item('any_object')->show();
$page->item('any_object')->setVisible(true);

// 四角形, 楕円形, 線形
$page->item('rect_id')->setStyle('border_width', 1)
                      ->setStyle('border_color', '#0000ff')
                      ->setStyle('fill_color', '#ff0000')

// テキスト, テキストブロック
$page->item('text_id')->setStyles(array(
    'color'       => 'blue',
    'align'       => 'center', // left, center, right
    'valign'      => 'bottom'  // top, center, bottom
    'font_size'   => 20,
    'bold'        => true,
    'italic'      => false,
    'linethrough' => true,
    'underline'   => false
));
```

### PDF データを取得する

Hello World では、PDF ファイルを作成しましたが Web アプリで PDF をレスポンスする場合などは、下記のように PDF データを返すことで実現できると思います。

```php
$report->generate(); // => PDF data
```

## 注意しとくと良いこと

### 本家 Thinreports の一部の機能に未対応

まだ alpha リリースということもあって、本家 Thinreports の一部の機能に対応していません。

  * 一覧表機能
  * 複合レイアウト
  * PDF のセキュリティ設定

など。詳細は [こちら](https://github.com/thinreports-php/thinreports-php/tree/master#not-implemented)。

### 使えるフォントは 4 種類のみ

Thinreports の仕様ですが、フォントは下記 4 種類しか使えません。

  * Helvetica
  * Times New Roman
  * Courier New
  * IPAフォント

本家 Thinreports v1.0 でカスタムフォント機能が来て、thinreports-php でも対応すれば解決するかもしれません。

## 今後

（2015.7.27 修正）

0.8.0-alpha2 で PHP5.3 以降をサポートして、0.8.0 正式版で以下のような感じになる予定です（RC を挟むかも）

  * 複合レイアウトサポート
  * メモリ消費, パフォーマンス向上
  * 一覧表機能サポート（予定）

詳細は [マイルストーン](https://github.com/thinreports-php/thinreports-php/milestones) をご覧ください。

興味のある方は、Gitter の [開発コミュニティ](https://gitter.im/thinreports-php/thinreports-php/dev) を覗いてみると良いかもしれません。