忍び歩く男 - SLYWALKER

大阪のこっそりPHPer

CakePHP1.2RC3でPDFを作成するときのメモ

上を参考にした。
すんなり行くかと思ったら、案外ハマったのでメモ

FPDFダウンロード

FPDF
Downloadsからv1.6をゲット
What languages can I use?
のところからJapaneseのリンク、japanese.zipをゲット

FPDI、FPDF-TPLダウンロード

Setasign :: Downloads of FPDI and FPDF_TPL
FPDIとFPDF-TPLをゲット

インストール

vendors/
 fpdf/ FPDFからゲットしたファイルを解凍して入れる。japanese.zipの中身もここへ
 fpdi/ FPDI、FPDF-TPLからゲットしたファイルを解凍してここへ

fpdf/japanese.phpを変更

-require('fpdf.php');
+App::import('Vendor', 'FPDF', array('file' => 'fpdf/fpdf.php'));
+App::import('Vendor', 'FPDI', array('file' => 'fpdi/fpdi.php'));

-$SJIS_widths=array(...省略...); // クラスのプロパティにする

-class PDF_Japanese extends FPDF
+class PDF_Japanese extends FPDI
{

+    var $SJIS_widths=array(...省略...);

     //Add SJIS font with proportional Latin
     $name='KozMinPro-Regular-Acro';
-    $cw=$GLOBALS['SJIS_widths'];
     $CMap='90msp-RKSJ-H';
     $registry=array('ordering'=>'Japan1','supplement'=>2);
-    $this->AddCIDFonts($family,$name,$cw,$CMap,$registry);
+    $this->AddCIDFonts($family,$name,$this->SJIS_widths,$CMap,$registry);

/app/views/helpers/fpdf.php

<?php
App::import('Vendor', 'PDF_Japanese', array('file' => 'fpdf/japanese.php'));

if (!defined('PARAGRAPH_STRING')) {
    define('PARAGRAPH_STRING', '~~~');
}

define('FPDF_FONTPATH', VENDORS . 'fpdf/font/');
define('FPDFHELPER_INTERNAL_ENCODING', 'UTF-8');

class FpdfHelper extends PDF_Japanese {
    // 追記[2008-10-31]: これをいれとかないと怒られた
  public $helpers = array();

    // ハマリポイント!
  // これを書いとかないと$orientationに空配列が入ってエラーになる。なんで?
    function __construct()
    {
        $this->PDF_Japanese();
    }

    function setup($orientation = 'P', $unit = 'mm', $format = 'A4')
    {
        $this->PDF_Japanese($orientation, $unit, $format);
    }

    function fpdfOutput($name = 'page.pdf', $destination = 's')
    {
        return $this->Output($name, $destination);
    }

    function Cell($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = 0, $link = '')
    {
        parent::Cell($w, $h, $this->conv_sjis($txt), $border, $ln, $align, $fill, $link);
    }

    // 追記[2008-10-31]: 改行入りセルが使いたかったので
    function SJISMultiCell($w, $h, $txt, $border = 0, $align = 'J', $fill = false)
    {
        // 変更[2008-10-31]: 勝手に改行されて使いづらかったので
        $x = $this->GetX();
        $y = $this->GetY();
        parent::SJISMultiCell($w, $h, $this->conv_sjis($txt), $border, $align, $fill);
        $this->SetY($y);
        $this->SetX($x + $w);
    }

    function Text($x, $y, $txt)
    {
        parent::Text($x, $y, $this->conv_sjis($txt));
    }

    function conv_sjis($txt)
    {
        // 追記[2008-10-31]: 重複エンコード防止
    //return mb_convert_encoding($txt, "SJIS-win", FPDFHELPER_INTERNAL_ENCODING);
        return mb_convert_encoding($txt, "SJIS-win", FPDFHELPER_INTERNAL_ENCODING . ", SJIS-win");
    }
}
?>

使ってみる

/app/views/layouts/pdf.ctp

<?php
header('Content-type: application/pdf');
//header('Content-type: text/html');
// ハマリポイント!
// キャッシュが残らないようにしないと確認時にあたふたする
header('Cache-Control: no-store, no-cache, must-revalidate');
echo $content_for_layout;
?>

なんか動きがおかしいときは Content-type を text/html にしてエラーを確かめる

/app/controllers/tests_controller.php

<?php
class TestsController extends AppController {
    public $name = 'Tests';
    public $helpers = array('Fpdf');
    public $uses = array();

    function index()
    {
        // denug を 0 にしとかないと悲惨
        Configure::write('debug', 0);
        $this->layout = 'pdf';
        $this->set('data','ハローワールド hello world!');
        $this->render();
    }
}
?>

/app/views/tests/index.ctp

<?php
$fpdf->AddSJISFont();
$fpdf->Open();
$fpdf->AddPage();
$fpdf->SetFont('SJIS', '', 16);
$fpdf->Cell(40, 10, $data);
$fpdf->Text(0, 10, 'テスト');
echo $fpdf->fpdfOutput();
?>