退職PDFメーカーの作り方

3,747 views
3,614 views

Published on

How to making resignation pdf maker.

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,747
On SlideShare
0
From Embeds
0
Number of Embeds
131
Actions
Shares
0
Downloads
1
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

退職PDFメーカーの作り方

  1. 1. ~ベタなPHP開発手法~ 2013/01/22 “よや” <yoya@awm.jp> 退職届PDFメーカーの作り方
  2. 2. 自己紹介  昨年まで PHP + C言語、たまに JavaScript でお仕事してました。  趣味で公開してるライブラリ (Flashバイナリ操作)  http://sourceforge.jp/projects/swfed  http://openpear.org/package/IO_SWF  ImageMagick のストーカーやってます。  http://d.hatena.ne.jp/yoya/searchdiary?word=Ima geMagick
  3. 3. 発表内容  退職届PDFメーカーについて  普通のPHPプログラミング  普通じゃない(?)PHPプログラミング  PDF 出力について  iframe を使った PDF 表示  壁紙機能 (ストレージ、擬似α透過)  QR コード対応
  4. 4. 退職届PDFメーカーとは  参考) http://gigazine.net/news/20140105- resignation-letter-generator/  http://app.awm.jp/resign/ 退職届PDFメーカー
  5. 5. 利用者様の喜びの声!?
  6. 6. 普通のPHPプログラミング  SSI (server side include) 風  CGI (common gateway interface) 風  テンプレートエンジン(Smarty)  フレームワーク?
  7. 7. 普通の PHP プログラミング(1/4)  SSI(server side include) 的な使い方 <html> <head><title> 1 </title> </head> <body> <?php echo date("Y/m/d H:i:s"); ?> </body> </html>  http://awm.jp/~yoya/study/php/sagami/1/1.php
  8. 8. 普通の PHP プログラミング(2/4)  CGI (common gateway interface) 的な使い方 <?php echo "<html>¥n"; echo "<head><title> 2 </title> </head>¥n"; echo "<body>¥n"; echo date("Y/m/d H:i:s"); echo "</body> </html>¥n"; ?>  http://awm.jp/~yoya/study/php/sagami/1/2.php
  9. 9. 普通の PHP プログラミング(3/4)  テンプレートエンジン(Smarty) で http://awm.jp/~yoya/study/php/sagami/1/3.tpl <html> <head><title> 3 </title> </head> <body> {$now} </body> </html> <?php require_once('Smarty.class.php'); $smarty = new Smarty(); $smarty->assign('now', date("Y/m/d H:i:s")); $smarty->display('3.tpl');  http://awm.jp/~yoya/study/php/sagami/1/3.php
  10. 10. 普通の PHP プログラミング(4/4) PHPフレームワーク CakePHP ? ZendFramework ? Symphony ? CodeIgniter ? ↑省略!!! こういったページでも見て下さい > http://antenasites.com/2013/07/php-framework/ いずれにしても HTML 出力の話ばかり \今回もはそういう話はしません/ そもそも、僕は普通の発表した事ないです。
  11. 11. 普通じゃないPHPプログラミング \HTML 以外を出力してみよう/  PHP は HTML 以外にも色々出力出来ます。
  12. 12. PHP で HTML じゃないモノ出力  JPEG/PNG画像出力  PDF 出力  Excel 出力 (要望があれば次回に解説)  Spreadsheet/Excel/Writer はそのままだと PHP5.4 で動かないんですよね…
  13. 13. PNG画像出力 (1/2) <?php header ('Content-type: image/png'); $im = imagecreate(240, 240); $red = imagecolorallocate($im, 255, 0, 0); $green = imagecolorallocate($im, 0, 255, 0); $blue = imagecolorallocate($im, 0, 0, 255); imageline($im, 0, 0, 200, 200, $green); imageline($im, 0, 100, 200, 100, $blue); imagepng($im);  http://awm.jp/~yoya/study/php/sagami/1/line.php
  14. 14. PNG画像出力 (2/2) <?php header ('Content-type: image/png'); $im = imagecreate(240, 240); $palette = array(); for ($i = 0 ; $i < 256 ; $i++) { $palette []= imagecolorallocate( $im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255) ); } for ($y = 0 ; $y < 240 ; $y++) { for ($x = 0 ; $x < 240 ; $x++) { imagesetpixel($im, $x, $y, $palette[mt_rand(0, 255)]); } } imagepng($im);  http://awm.jp/~yoya/study/php/sagami/1/png.php
  15. 15. JPEG画像出力 <?php header ('Content-type: image/jpeg'); $im = imagecreate(240, 240); $palette = array(); for ($i = 0 ; $i < 256 ; $i++) { $palette []= imagecolorallocate( $im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255) ); } for ($y = 0 ; $y < 240 ; $y++) { for ($x = 0 ; $x < 240 ; $x++) { imagesetpixel($im, $x, $y, $palette[mt_rand(0, 255)]); } } imagejpeg($im);  http://awm.jp/~yoya/study/php/sagami/1/jpeg.php
  16. 16. PDF 出力  FPDF と PHPlib が有名  とりあえず FPDF を試す  インストール (Debian6) $ apt-cache search fpdf php-fpdf - PHP class to generate PDF files $ sudo apt-get install php-fpdf  日本語対応  http://www.fpdf.org/phorum/read.php?f=1&i=7977&t=79 77  japanese.zip と mbfpdf10b.zip があって後者の方が評 判が良いが、導入が楽なので前者を使ってみた  (実際に何が困るのか知りたかったのもある)  でも今の所、困る事がないので困ってる。
  17. 17. PDF 出力 (日本語対応)  japanese.php は SJIS(cP932) 前提  今時の PHP は日本語を UTF-8  変換する function Text($x,$y,$txt) { $txt = mb_convert_encoding($txt, "CP932", "UTF-8"); // ☆ parent::Text($x,$y,$txt); } require('japanese.php'); header('Content-Type: application/pdf;'); $pdf=new PDF_Japanese(); $pdf->AddSJISFont(); $pdf->AddPage(); $pdf->SetFont('SJIS','',18); $pdf->Text(100,60,'こんにちわ!'); $pdf->Output();  http://awm.jp/~yoya/study/php/sagami/1/fpdfj.php
  18. 18. PDF 出力 (縦書き対応)  rotation.php で回転出来るけど日本語未対応  継承で合体させてみた  書き換え require('japanese.php'); // class PDF_Rotate extends PDF // オリジナル class PDF_Rotate extends PDF_Japanese // ☆ { require('japanese.php'); header('Content-Type: application/pdf;'); $pdf=new PDF_Japanese(); $pdf->AddSJISFont(); $pdf->AddPage(); $pdf->SetFont('SJIS','',18); $pdf->Rotate(45 ,100, 60); $pdf->Text(100,60,'こんにちわ!'); $pdf->Output();  http://awm.jp/~yoya/study/php/sagami/1/fpdfr.php
  19. 19. 日本語対応 (縦書きレイアウト)  単純に1文字ずつ縦にしても駄目  90度倒さないと駄目なもの > ー (長音)  横がズレルもの > 」 (かぎ括弧)  縦書き用フォントならカーニングに情報 が入ってそうだけど、悲しいけどデバイ スフォントなのよね。。  デバイスフォントでPDF の容量を減らして、 さくさく操作感を重視している。
  20. 20. 日本語対応 (縦書きレイアウト)  失敗例を元に、対処前と対処後 バグってました 後で治します
  21. 21. 日本語対応 (縦書き無理やり対 応) switch ($c) { case 'ー': case '-': case '―': case '‐': case '~': $this->Rotate(90, $x+$fontSize*1.1, $y-$fontSize*1.1); $this->Text($x, $y, $c); $this->Rotate(0); break; case '、': case '。': case ',': case '.': $this->Text($x + $fontSize*1.5, $y - $fontSize*2, $c); break; case '」': case '”': $this->Text($x + $fontSize*1.5, $y, $c); break; default: $this->Text($x, $y, $c); break;
  22. 22. 日本語対応 (漢数字)  パターン  1 => 一  10 => 十  20 => 二十  21 => 二十一
  23. 23. 日本語対応 (漢数字 \力づく/) function date2japanize($date) { // range: 0 - 99 $from = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); $to = array('〇', '一', '二', '三', '四', '五', '六', '七', '八', '九'); $dates = split('-', $date); $dates[0] -= 1988; foreach (range(0, 2) as $idx) { $d = $dates[$idx]; if ($d < 10) { $d = mb_substr($d, 1); } elseif ($d == 10) { $d = '十'; } elseif ($d < 20) { $d = '十'.mb_substr($d, 1); } elseif (($d % 10) === 0) { $d = mb_substr($d, 0, 1).'十'; } else { $d = mb_substr($d, 0, 1).'十'.mb_substr($d, 1); } $dates[$idx] = str_replace($from, $to, $d); } return '平成'.$dates[0].'年'.$dates[1].'月'.$dates[2].'日'; }
  24. 24. iFrame を使った即時反映  http://app.awm.jp/resign/resign.php (トップ)  GET パラメータを読んで入力 フォームを埋め る  それと同時に iframe で pdf.php を表示する  http://app.awm.jp/resign/pdf.php  GET パラメータを読んで入力 FORM を埋める \それだけ/
  25. 25. 壁紙  普通のファイル送信フォーム <form enctype="multipart/form-data" action="?" method="POST"> <input type="hidden" name="MAX_FILE_SIZE" value="100000000" /> 壁紙用の画像ファイルをアップロード: <input name="image_file" type="file" class="btn btn-success" /> <input type="submit" value="画像ファイル送信" class="btn btn-primary" />  ファイルに一意な ID を付けて保存する  擬似αブレンディング処理をする
  26. 26. 壁紙 (ファイルに一意なIDを)  sha1 を使ってデータを数値に変換する  40文字は長いので12文字に減らす (衝突御免) function image_data2id($data, $ext) { // 16 chars digest $sha1 = sha1($data, true); $base64 = base64_encode(substr($sha1, 0, 12)); return strtr($base64, '+/', '-_').'.'.$ext; }  フォルダを分割して保存  1フォルダに大量のファイル置くの怖いので yoya@app.awm.jp:/<秘密>/app/resign/img$ ls 0H 1j 3g 6u 9L AP Cg Eu JY PB Ur XV ZC cx iI jm nL qP sN ve 0N 2D 3w 6z 9O AW DA F_ Kg S5 VG Xq _A dK iP kL oE rl sO xa 0x 2j 6k 8M A0 CH DN GR MU SE VR YM ao g0 ip lF oQ ry sn xs 17 33 6s 8p AA Ca Ed Hh Ni Un Wb Yj bM i1 ja lX pa sM tz z9
  27. 27. 壁紙 (αブレンディング)  元画像と白っぽく変換した画像を保存 yoya@app.awm.jp:/<秘密>/app/resign/img$ ls 17/ 17Pe9qdjx8OtTz4h.jpg _17Pe9qdjx8OtTz4h.jpg  (PNG は大丈夫だけど) JPEG 画像に対して PDF に半透明の機能が見つからなかった ので、擬似アルファブレンディング
  28. 28. 擬似αブレンディング  あらかじめ画像を白くしておけば、その まま重ねても半透明で張ったように見え る。 function filterPixel(&$red, &$green, &$blue) { $red = (255 * 6 + $red) / 7; $green = (255 * 6 + $green) / 7; $blue = (255 * 6 + $blue) / 7; }
  29. 29. QRコード対応  PHP QR Code encoder を使ってます  http://phpqrcode.sourceforge.net/  処理が重たいので大規模サイトではお勧 め出来ませんが、趣味では十分です。 require('phpqrcode.php'); $url = (empty($_SERVER["HTTPS"]) ? "http://" : "https://") . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]; $url = substr($url, 0, strlen($url) - strlen('&ext=.pdf')); $tmpfile = tempnam('tmp', 'qr'); QRcode::png($url, $tmpfile, 'L', 4, 0); $pdf->Image($tmpfile, 25, 220, 40, 40, 'png'); unlink($tmpfile);
  30. 30. Github で公開中  https://github.com/yoya/resign  簡単な説明も  http://pwiki.awm.jp/~yoya/?resign
  31. 31. 質問コーナー  Q) sha1 の第二引数 false にすれば base64_encode 要らない?  気付きませんでした!でも互換性怖いのでこのままで。  Q) jpeg も png で保存すれば半透明対応できない?   Jpeg と png でリサイズのレンダリングが違う可能性があるので。 あと、容量増えるの嫌だったので。(後付け理由)  Q) 反響はどうですか   おかげ様で400を超えるブクマを頂いてます。 利用者の方から直接ありがとうメールを貰ったりもします。  Q) 生成された PDF を手元にこっそり保存してません? URL で完全に再現できるので access_log を保存すれば出来るけど、 誓ってみてません。  あと、万が一のサーバクラックが怖いので、日付でにファイルを 切り替えてて古いのは消してます。見てませんよ! 
  32. 32. おわり

×