Symfoware

Symfowareについての考察blog

PHP 5.6 + CodeIgniter 3 + ThinreportsでPDF帳票を出力する

オープンソース PDF 帳票ツール「Thinreports」
http://www.thinreports.org/

Chromeの拡張機能で帳票定義ができるというのは面白い。

Composerで導入可能なPHP拡張があるようなので、
CodeIgniterと組み合わせて使ってみます。


Composer



試しているOSはFreeBSD 10.1 + PHP 5.6.11です。

以前試した手順を元に、thinreports-phpを導入します。
CodeIgniter 3でComposer(コンポーザー)のautoload


applicationフォルダに、「composer.json」というファイルを作成。
内容は以下のとおり。


{
    "require": {
        "thinreports-php/thinreports-php": "@alpha"
    }
}




applicationフォルダに移動して、composerコマンドを実行。


# composer install




auto_loadを有効にするため、application/config/config.phpを編集。


  1. $config['composer_autoload'] = TRUE;




これで下準備は完了です。





Controller



最初はコマンドを実行してPDF出力を試してみます。

application/vendor/thinreports-php/thinreports-php/examples/hello_world/hello_world.tlfを
application/viewにコピーしました。

定義はこんな感じです。

635_01.png


サンプルを参考にControllerを作成。


  1. <?php
  2. defined('BASEPATH') OR exit('No direct script access allowed');
  3. class Sample extends CI_Controller {
  4.     public function index() {
  5.         
  6.         date_default_timezone_set('Asia/Tokyo');
  7.         
  8.         $report = new Thinreports\Report(VIEWPATH . DIRECTORY_SEPARATOR . 'hello_world.tlf');
  9.         $page = $report->addPage();
  10.         $page->item('world')->setValue('World');
  11.         $page->item('sekai')->setValue('世界');
  12.         
  13.         $report->generate(VIEWPATH . DIRECTORY_SEPARATOR . 'hello_world.pdf');
  14.         
  15.         echo "ok\n";
  16.         
  17.     }
  18. }




コマンドで実行すると


# php index.php sample




こんなエラーになります。


Severity: ErrorMessage: Class 'SimpleXMLElement' not found
Filename: /var/dev/php/thinreports/application/vendor/thinreports-php/thinreports-php/src/Thinreports/Generator/LayoutRenderer.phpLine Number: 33




拡張機能が足りないようなのでインストール。


# pkg install php56-simplexml




次のエラーはこれ。


Severity: ErrorMessage: Call to undefined function gzcompress()
Filename: /var/dev/php/thinreports/application/vendor/tecnick.com/tcpdf/include/tcpdf_fonts.phpLine Number: 370




拡張機能をインストール。


# pkg install php56-zlib




改めて、コマンドを実行すると


# php index.php sample



こんなPDFが作成できました。

635_02.png




値の指定方法



サンプルそのままですが、色々な指定方法がありますね。


  1. // $page->item('name')->setValue('値')
  2. $page = $report->addPage();
  3. $page->item('world')->setValue('World');
  4. $page->item('sekai')->setValue('世界');
  5. // $page('name')->setValue('値')
  6. $page = $report->addPage();
  7. $page('world')->setValue('World');
  8. $page('sekai')->setValue('世界');
  9. // $page->setItemValue('name', '値')
  10. $page = $report->addPage();
  11. $page->setItemValue('world', 'World');
  12. $page->setItemValue('sekai', '世界');
  13. // 無名関数で
  14. $report->addPage(function ($new_page) {
  15.     $new_page('world')->setValue('World')->setStyle('color', 'blue');
  16.     $new_page('sekai')->setValue('世界');
  17. });
  18. // $page->setItemValues(array())
  19. $page = $report->addPage();
  20. $page->setItemValues([
  21.     'world' => 'World',
  22.     'sekai' => '世界'
  23. ]);
  24. $report->addPage()->setItemValues([
  25.     'world' => 'World',
  26.     'sekai' => '世界'
  27. ]);







フォントカラーの設定



色の設定を行ってみます。


  1. <?php
  2. defined('BASEPATH') OR exit('No direct script access allowed');
  3. class Sample extends CI_Controller {
  4.     public function index() {
  5.         
  6.         date_default_timezone_set('Asia/Tokyo');
  7.         
  8.         $report = new Thinreports\Report(VIEWPATH . DIRECTORY_SEPARATOR . 'hello_world.tlf');
  9.         $page = $report->addPage();
  10.         $page->item('world')->setValue('World');
  11.         $page->item('sekai')->setValue('世界');
  12.         
  13.         // worldの色を変更
  14.         $page->item('world')->setStyle('color', 'blue');
  15.         
  16.         $report->generate(VIEWPATH . DIRECTORY_SEPARATOR . 'hello_world.pdf');
  17.         
  18.         echo "ok\n";
  19.         
  20.     }
  21. }




これは便利。

635_03.png




ブラウザで表示



せっかくCodeIgniterなので、ブラウザでPDFを表示してみます。


  1. <?php
  2. defined('BASEPATH') OR exit('No direct script access allowed');
  3. class Sample extends CI_Controller {
  4.     public function index() {
  5.         
  6.         date_default_timezone_set('Asia/Tokyo');
  7.         
  8.         $report = new Thinreports\Report(VIEWPATH . DIRECTORY_SEPARATOR . 'hello_world.tlf');
  9.         $page = $report->addPage();
  10.         $page->item('world')->setValue('World');
  11.         $page->item('sekai')->setValue('世界');
  12.         
  13.         // worldの色を変更
  14.         $page->item('world')->setStyle('color', 'blue');
  15.         
  16.         $pdf_file = VIEWPATH . DIRECTORY_SEPARATOR . 'hello_world.pdf';
  17.         $report->generate($pdf_file);
  18.         
  19.         $this->output
  20.             ->set_content_type('application/pdf')
  21.             ->set_output(file_get_contents($pdf_file));
  22.         
  23.     }
  24. }




http://[サーバーIP]/sampleで、PDFが表示されると思います。

635_04.png





ファイル出力なしでブラウザに表示



※2015/8/5追記

コメントいただいたので、ファイル出力せずに直接ブラウザに
PDFを表示する方法を試してみます。


その前に


  1. date_default_timezone_set('Asia/Tokyo');



この関数呼び出しをコメントするとこんなエラーになります。


A PHP Error was encountered

Severity: Warning

Message: date(): It is not safe to rely on the system's timezone settings.
You are *required* to use the date.timezone setting or the date_default_timezone_set() function.
In case you used any of those methods and you are still getting this warning,
you most likely misspelled the timezone identifier.
We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone.

Filename: include/tcpdf_static.php

Line Number: 904




これはphp.iniにdate.timezoneの設定が無いからです。
雛形のファイルをコピーして、php.iniを作成。
編集します。


# cp /usr/local/etc/php.ini-development /usr/local/etc/php.ini
# vi /usr/local/etc/php.ini




date.timezone = 'Asia/Tokyo'を追加。


[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = 'Asia/Tokyo'




これで、date_default_timezone_setの呼び出しが不要となります。

次に、ファイル出力なしでブラウザに表示する方法ですが、


  1. $report->generate();



このようにgenerateを引数なしで呼び出すと、
ファイルに出力するはずだったPDFの内容が取得できますので、
そのままレスポンスに渡してやります。

修正後のソースはこうなりました。


  1. <?php
  2. defined('BASEPATH') OR exit('No direct script access allowed');
  3. class Sample extends CI_Controller {
  4.     public function index() {
  5.         
  6.         $report = new Thinreports\Report(VIEWPATH . DIRECTORY_SEPARATOR . 'hello_world.tlf');
  7.         $page = $report->addPage();
  8.         $page->item('world')->setValue('World');
  9.         $page->item('sekai')->setValue('世界');
  10.         
  11.         // worldの色を変更
  12.         $page->item('world')->setStyle('color', 'blue');
  13.         
  14.         $this->output
  15.             ->set_content_type('application/pdf')
  16.             ->set_output($report->generate());
  17.         
  18.     }
  19. }


関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2015/08/04(火) 22:01:21|
  2. PHP
  3. | トラックバック:0
  4. | コメント:2
  5. | 編集
<<Java JSONICでjsonな文字列をオブジェクトに直接デコード | ホーム | PDFライブラリ Apache PDFBoxで画像をPDFに埋め込む>>

コメント

開発者の hidakatsuya と申します。試していただきありがとうございます。

ブラウザで出力するコードですが、下記のようにするとファイルに保存することなく直接出力できると思います。

$this->output
->set_content_type('application/pdf')
->set_output($report->generate());

それと date_default_timezone_set() ですが、これは php.ini などで設定しておけば、コールする必要はなくなります。その他、リファレンスがなくてアレなんですが、動的に画像を埋め込んだりもできますので今後もチェックしていただけると幸いです。
  1. 2015/08/04(火) 23:42:37 |
  2. URL |
  3. hidakatsuya #-
  4. [ 編集 ]

コメント、ありがとうございます。
記事に追記しておきますね。
  1. 2015/08/05(水) 21:22:42 |
  2. URL |
  3. symfo #-
  4. [ 編集 ]

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1780-78e0fd04
この記事にトラックバックする(FC2ブログユーザー)