cakephp3.6でphpwkhtmltopdf使ってPDFを作る

作業環境

cakephp3.6
centos6.9
apache2.4
mysql5.6
php7.1

概要

cakephp3でPDF作りたかった。
bootstrapとか使ってたらcol効かなかったのでもし横並びで困ったらこの記事をどうぞ

やったこと

●参考

インストールはほぼこのサイトのまま作業できたのでよかった。
ありがたすぎます。

必要なライブラリのインストール

# yum install fontconfig libXrender libXext xorg-x11-fonts-Type1 xorg-x11-fonts-75dpi freetype libpng zlib libjpeg-turbo

Bit数の確認

# uname -a
Linux localhost.localdomain 2.6.32-696.30.1.el6.x86_64 #1 SMP Tue May 22 03:28:18 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

x86_64とあるし64bitのようなので64bit用のRPMパッケージのインストール
wget先は下記公式のDLページのURLを使ってるよ
https://wkhtmltopdf.org/downloads.html

# wget https://downloads.wkhtmltopdf.org/0.12/0.12.5/wkhtmltox-0.12.5-1.centos6.x86_64.rpm
# rpm -Uvh wkhtmltox-0.12.5-1.centos6.x86_64.rpm

一応場所を確認する

# which wkhtmltopdf
/usr/local/bin/wkhtmltopdf

日本語フォントを利用する

# wget http://dl.ipafont.ipa.go.jp/IPAexfont/IPAexfont00301.zip
# unzip IPAexfont00301.zip
# mv IPAexfont00301 /usr/share/fonts

今回はcakephp3で使うのでcomposerでrequreしようと思う
phpで利用するためのラッパークラスがあるそうなので、それもcomposerでインストールする
https://github.com/mikehaertl/phpwkhtmltopdf ちなみにこれ
もしかしたらcakepdf入れなくてもいいかも

# composer require mikehaertl/phpwkhtmltopdf
# composer require friendsofcake/cakepdf

cakephpの適当なコントローラーにpdf作ってファイル名返すやつを書いてみる

//ファイルの頭の方でuseする
use mikehaertl\wkhtmlto\Pdf;

	(中略)

	//PDF作成してjsonでファイル名だけ返す感じのやつ
	public function pdf(){
		$this->autoRender = FALSE;
		
		//html本体作成、試したときはヘッダフッタがないとうまく動かなかった
		$html = <<<EOT
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
	<head>
		<meta content="text/html; charset=UTF-8" http-equiv="content-type">
		<meta name="robots" content="noindex,nofollow,noarchive">
		<meta http-equiv="Pragma" content="no-cache">
		<meta http-equiv="Cache-Control" content="no-cache">
		<meta http-equiv="Expires" content="0">
		<title>PDF</title>
	</head>
	<body>
		<style>
		/* 強制的にサーバーにある日本語フォントにする */
		body {
			font-family: "PAexGothic", "IPAexゴシック";! important
		}
		/* PDFに入れないデータの非表示、PDFに入れるデータの表示 */
		.pdf-hide{
			display: none !important;
		}
		.pdf-show{
			display: block !important;
		}
		/* 改ページ処理 */
		.pdf-page-breaker{
			page-break-before: always !important;
		}
		</style>
		
		<h1>この辺にPDFに変換したいhtmlとか書いておく</h1>
	</body>
</html>
EOT;

		// PDFにする直前のhtmlを保存するとpdfにしたときとの差異がわかる
		$file = '/var/www/html/pre_pdf.html';
		file_put_contents($file, $html);

		$pdf = new Pdf([
			//javascript実行待ち
			'javascript-delay' => 1000,
			'page-size' => 'A4',
			// バイナリの位置とエンコード形式
			'binary'   => '/usr/local/bin/wkhtmltopdf',
			'encoding' => 'utf-8',
			//用紙横向き
			'orientation' => 'landscape',
			'ignoreWarnings' => true,
			'commandOptions' => array(
				'procEnv' => array(
					'LANG' => 'ja_jp.utf-8',
				),
			),

			// PDFを端まで利用するときは0にする
			'margin-top'    => 5,
			'margin-right'  => 0,
			'margin-bottom' => 0,
			'margin-left'   => 0,
			'no-outline',
		]);
		$pdf->addPage($html);

		// PDFを保存
		$filename = 'main.pdf';
		$pdf->saveAs($filename);

		// json返却
		if($pdf->getError() === ''){
			$data['message'] = 'OK';
			$data['filename'] = $filename;
			$json             = json_encode( $data );
			return $this->response->withType('application/json')->withStringBody($json);
		}else{
			$data['message'] = $pdf->getError();
			$json            = json_encode( $data );
			return $this->response->withType('application/json')->withStringBody($json);
		}

	}

おわり。