1月 28

PHP5.3で#は非推奨(いまさら)

特に変更を加えていない処理を通るテストをしていると、
Deprecated: Comments starting with '#' are deprecated
と大量の非推奨メッセージが。
どうやらPHP5.3から#のコメントは非推奨になったとのことで、そのエラーが出ていたようです。

ちょっと前に、Yahoo!ウォレット実装のために5.3に上げたのが原因でしょう。
そういえば、まだ審査結果が来ないのですが。

通常のスクリプトには#は使わないのですが、iniファイルでは普通に使っていました。
perlと共用できる利点があったのですが、これで分けないといけなくなったのはちょっと残念です。

10月 23

PHPのセッション管理はスッキリさせたい

PHPで手続きの途中で別のことをさせてまた戻るときに、
セッションに中断した情報を保存させたりします。
また、リダイレクト先でメッセージを表示させたいときにも利用しますね。

いままでは
$_SESSION['notice'] = $_SERVER['REQUEST_URI'];

$location = './';
if( isset($_SESSION['location']) ){
$location = $_SESSION['location'];
unset($_SESSION['location']);
}
header("Location: $location");

とかやったりするわけですが、あちこちでこんな処理を書くのはダサいですよね。

なので、ユーザ用クラスを作って放り込むことにしたわけです。
手続の中断情報を入れるために、カッコよくInterceptとでもしましょう。

class USER {

public function setIntercept( $location ){
$_SESSION['location'] = $location;
}
public function getIntercept( $flagClear=false ){
if( !isset($_SESSION['location']) ){ return; }
$location = $_SESSION['location'];
if( $flagClear ){ $this->clearLocation(); }
return $location;
}
public function clearLocation(){
if( !isset($_SESSION['location']) ){ return 0; }
unset($_SESSION['location']);
return 1;
}

}

こんな感じでスッキリさせました。
※コードは直書きでtypoちゃんと見てません、あしからず。

8月 14

PHPのSmartyテンプレート内でstr_repeatを使う

テンプレートエンジンSmartyでのお話。
PHPの関数も基本的には使用できるのですがパラメータで何時も同だったらちょっと悩むので、検索したらヒットするように残しておこうかなと。
マニュアルを見なくても大体わかりますよね。
string str_repeat ( string $input , int $multiplier )
PHPでstr_repeat(1,2)と書くものは、
Smartyでは第1パラメータを先頭に持ってきて、{1|str_repeat:2}となります。
一度使うとしばらくは覚えてるんですが、なぜか忘れてしまっていますね。

6月 27

ImageMagickの動作が重いオプション

開発環境のWindows7上では全く問題にならなかった、dissolveオプション。
明るさを調整したかったものの、brightness-contrastがバージョンの都合で使えず、modulateはコントラストだったので、白い画像を作成してdissolveで透明度を指定して合成するように調整してみた。
開発機では問題がなく、いざVPSに上げると動作が遅い、というか重い。
これは使えたもんじゃない。
まだmodulateの方がまし。
この感じだと、むりにOSのバージョン上げてImageMagickを上げても動作が遅い可能性もあるわけで、どうしたものか。
処理によってPHPとPerlが走って、結果は同じにならないと困るので、言語ごとにチューンされてるGDも少し危険な感じ。

困った困った。

3月 16

PHPのsimplexmlでハマる

PHPでXMLファイルを使用する必要がありました。
多段階層のデータを参照配列で扱いたいのです。
PHPでXMLファイルを作成して、Perlのスクリプトで使用するというプロセスです。
PHPのセッションに格納しておいて、セッションファイルを直接読みに行かせるなども考えたのですが、
メンテナンスを考えて結局XMLファイルを用意する方法に決定。

XMLファイルをPHPで読み直す際に問題が発生。
ノードがオブジェクトのまま、simpleXMLElementになっていて扱いづらい。
単階層の場合は、(string)$hogeとか、“$hoge”とかするだけで何とかなるのですが、多段階層の場合はそうもいきません。
他に構造を扱う関数としてjson_decode(json_encode($hoge),true)で何とかなるかと思いきや、空値が配列になってしまう問題が発生。空値用の特別文字「{empty}」などを用意してみたりしても、判定を追加する箇所が多すぎで挫折。
さらに、「<!CDATA[fuga]]>」も配列になることが判明、まったく使い物になりませんでした。

最終的には、ドキュメントで何を言っているのかよくわからなかったパラメータを適当に採用していたら、希望する動作を見せたので落ち着きました。
結局はこうなりました。
simplexml_load_file( $set_file, 'simpleXMLElement', LIBXML_NOCDATA )

PHPは、関数の動作がこうもいい加減なものが多いですね。
互換のためにいろんなパラメータが追加されたり、関数名が変更になったりと振り回され続けるしかないですね。

6月 22

PHP5.3に怒られる

PHPを5.3にアップデートすると、今までのスクリプトが動かなかったりエラーが表示されるようになったりする。
特に、split関数を使うなコノヤローと、
「Deprecated: Function split() is deprecated in…」
と怒られるので、見逃してもらえるようphp.iniに呪文を唱える。
「error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED」
標準では、
「error_reporting = E_ALL」
となっているのでコメントアウトしておこう。
php.iniを保存して、httpdをリスタートさせれば、エラー表示が消えるはずです。
とりあえず、今後はsplitを使うのをやめて、explodeを使うように心がけよう。
でめたしでめたし。

6月 07

郵便番号から都道府県を調べる

PHPで郵便番号から都道府県を導く処理が必要になりました。

郵便番号から住所を調べるには、日本郵便で公開されているCSVをDBに突っ込んで、クエリを投げるのですが、データサイズもでかいし、市区町村までは必要がないのでとりあえず都道府県だけを簡単に調べる方法がないか探していました。

適当に調べていたところ、郵便番号の先頭2桁を見ればいいだろうという記事が多いものの、一部の都道府県は他県に混ざっているものがあるらしいく、それに対応したコードが見つからなかったので、日本郵便の検索と格闘しながら新しくコードを用意することにしました。

で、以下のようになりました。
とりあえず動けばいいので、処理速度の最適化は確認していません。

/*==============================================================================
 郵便番号から、都道府県番号を取得する簡易版

	要素:
		郵便番号(nnn-nnnn or nnnnnnn)
	戻り値:
		都道府県番号

	※ 備考:
		1 	北海道
		2 	青森県
		3 	岩手県
		4 	宮城県
		5 	秋田県
		6 	山形県
		7 	福島県
		8 	茨城県
		9 	栃木県
		10 	群馬県
		11 	埼玉県
		12 	千葉県
		13 	東京都
		14 	神奈川県
		15 	新潟県
		16 	富山県
		17 	石川県
		18 	福井県
		19 	山梨県
		20 	長野県
		21 	岐阜県
		22 	静岡県
		23 	愛知県
		24 	三重県
		25 	滋賀県
		26 	京都府
		27 	大阪府
		28 	兵庫県
		29 	奈良県
		30 	和歌山県
		31 	鳥取県
		32 	島根県
		33 	岡山県
		34 	広島県
		35 	山口県
		36 	徳島県
		37 	香川県
		38 	愛媛県
		39 	高知県
		40 	福岡県
		41 	佐賀県
		42 	長崎県
		43 	熊本県
		44 	大分県
		45 	宮崎県
		46 	鹿児島県
		47 	沖縄県

 2011-06-06 新設
------------------------------------------------------------------------------*/
function _prefecture_from_zip( $zip ){

	     if( preg_match( '/^01/',     $zip ) ){ return  5; } // "秋田県";   }
	else if( preg_match( '/^02/',     $zip ) ){ return  3; } // "岩手県";   }
	else if( preg_match( '/^03/',     $zip ) ){ return  2; } // "青森県";   }
	else if( preg_match( '/^0[4-9]/', $zip ) ){ return  1; } // "北海道";   }
	else if( preg_match( '/^1[0-9]/', $zip ) ){ return 13; } // "東京都";   }
	// ^20は欠番
	else if( preg_match( '/^2[1-5]/', $zip ) ){ return 14; } // "神奈川県"; }
	else if( preg_match( '/^2[679]/', $zip ) ){ return 12; } // "千葉県";   }
	// ^28は欠番
	else if( preg_match( '/^3[01]/',  $zip ) ){ return  8; } // "茨城県";   }
	else if( preg_match( '/^32/',     $zip ) ){ return  9; } // "栃木県";   }
	else if( preg_match( '/^3[3-6]/', $zip ) ){ return 11; } // "埼玉県";   }
	else if( preg_match( '/^37/',     $zip ) ){ return 10; } // "群馬県";   }
	else if( preg_match( '/^3[89]/',  $zip ) ){ return 20; } // "長野県";   }
	else if( preg_match( '/^40/',     $zip ) ){ return 19; } // "山梨県";   }
	else if( preg_match( '/^4[1-3]/', $zip ) ){ return 22; } // "静岡県";   }
	else if( preg_match( '/^4[4-9]/', $zip ) ){ return 23; } // "愛知県";   }
	else if( preg_match( '/^50/',     $zip ) ){ return 21; } // "岐阜県";   }
	else if( preg_match( '/^51/',     $zip ) ){ return 24; } // "三重県";   }
	else if( preg_match( '/^520\-?046[1-5]$/', $zip ) ){ return 26; } // "京都府";   } // 特殊
	else if( preg_match( '/^52/',     $zip ) ){ return 25; } // "滋賀県";   }
	else if( preg_match( '/^5[3-9]/', $zip ) ){ return 27; } // "大阪府";   }
	else if( preg_match( '/^6[0-2]/', $zip ) ){ return 26; } // "京都府"; }
	else if( preg_match( '/^630\-?027[12]$/',  $zip ) ){ return 27; } // "大阪府"; } // 特殊
	else if( preg_match( '/^63/',     $zip ) ){ return 29; } // "奈良県"; }
	else if( preg_match( '/^64/',     $zip ) ){ return 30; } // "和歌山県"; }
	else if( preg_match( '/^6[5-7]/', $zip ) ){ return 28; } // "兵庫県"; }
	else if( preg_match( '/^68/',     $zip ) ){ return 31; } // "鳥取県"; }
	else if( preg_match( '/^69/',     $zip ) ){ return 32; } // "島根県"; }
	else if( preg_match( '/^7[01]/',  $zip ) ){ return 33; } // "岡山県"; }
	else if( preg_match( '/^7[23]/',  $zip ) ){ return 34; } // "広島県"; }
	else if( preg_match( '/^7[45]/',  $zip ) ){ return 35; } // "山口県"; }
	else if( preg_match( '/^76/',     $zip ) ){ return 37; } // "香川県"; }
	else if( preg_match( '/^77/',     $zip ) ){ return 36; } // "徳島県"; }
	else if( preg_match( '/^78/',     $zip ) ){ return 39; } // "高知県"; }
	else if( preg_match( '/^79/',     $zip ) ){ return 38; } //"愛媛県"; }
	else if( preg_match( '/^8[0-3]/', $zip ) ){ return 40; } // "福岡県"; }
	else if( preg_match( '/^84/',     $zip ) ){ return 41; } // "佐賀県"; }
	else if( preg_match( '/^85/',     $zip ) ){ return 42; } // "長崎県"; }
	else if( preg_match( '/^86/',     $zip ) ){ return 43; } // "熊本県"; }
	else if( preg_match( '/^87/',     $zip ) ){ return 44; } //"大分県"; }
	else if( preg_match( '/^88/',     $zip ) ){ return 45; } // "宮崎県"; }
	else if( preg_match( '/^89/',     $zip ) ){ return 46; } // "鹿児島県"; }
	else if( preg_match( '/^90/',     $zip ) ){ return 47; } // "沖縄県"; }
	else if( preg_match( '/^91/',     $zip ) ){ return 18; } // "福井県"; }
	else if( preg_match( '/^92/',     $zip ) ){ return 17; } // "石川県"; }
	else if( preg_match( '/^93/',     $zip ) ){ return 16; } // "富山県"; }
	else if( preg_match( '/^9[45]/',  $zip ) ){ return 15; } // "新潟県"; }
	else if( preg_match( '/^9[67]/',  $zip ) ){ return  7; } // "福島県"; }
	else if( preg_match( '/^98/',     $zip ) ){ return  4; } // "宮城県"; }
	else if( preg_match( '/^99/',     $zip ) ){ return  6; } // "山形県"; }
	return NULL;

}

突込みがある人は遠慮なくどうぞ。
とりあえず、これで一つ機能が追加できたので、でめたしでめたし。

1月 23

TCPDFでOTFフォントを使用する

PHPでPDFを扱うためのライブラリにTCPDFがあります。
TCPDFでOTFフォントを使用すると、AcrobatReaderでは正常に読めても、Illustratorで正常に読めず、テキストがラスタライズされて少々気持ちの悪い事態に遭遇することとなります。
Illutratorで開くことを想定しているなら、TCPDFで扱うフォントには少々の工夫が必要なので、ここに残しておきます。

まず、TCPDFで扱うフォントはTTFフォントで統一します。フォント名が同じであればTTFで作成したPDFでも、OTFフォントがインストールされた環境のIllustratorでも問題なく読むことが出来ます。

OTFフォントをTTFフォントに変換するにはFontForgeを使用します。
インストール方法を検索すると、Windowsのcygwin環境下でのインストール方法が沢山ヒットしますが、個人的にはうまくいかなかったので、LinuxのCentOS5を使用しました。アプリケーションはGUIでx11環境が必要なので、デスクトップ版を用意しましょう。
パッケージはhttp://sourceforge.net/projects/fontforge/files/fontforge-executables/から「fontforge-20090923-1.i386.rpm」をダウンロードします。少々古いものですが、特に問題ありません。ダウンロードが終わると、ファイルをダブルクリックするだけでインストールが始まり、あっさりと完了します。

アプリケーションはGUIなのですが、メニューには登録されませんのでファイルを直接起動するか、ターミナルから起動する必要があります。ターミナルで「fontforge」と入力して起動すると、読み込むファイルを要求されるのでTTFフォントに変換したいOTFフォントを選択します。

選択したOTFファイルの内容によってはCIDマップファイルが必要と言われるかもしれません。CIDマップファイルはhttp://fontforge.sourceforge.net/cidmaps.tgzにありますので、ダウンロードして展開したファイルを「/usr/share/fontforge/」にコピーします。

しばらくして読み込みが完了すると文字コード表が表示されるので、メニューより「CID>単一化」を選択してファイルを統合します。
そしてメニューより「ファイル>フォントを保存」を選択して、保存形式を「TrueType」に設定し、保存ファイル名を入力して保存すれば完了です。
これで変換作業は完了です。作成されたTTFファイルを開いて正常に読み込むことができれば成功です。

フォントファイルをTCPDFで扱える状態にする方法は、ライブラリ内のtcpdf/fonts/utils/README.TXTにある通りで問題ありません。むしろ他に方法がありません。
「$ ttf2ufm -a -F myfont.ttf」
「$ php -q makefont.php myfont.ttf myfont.ufm」
これで作成されたファイルをfontsディレクトリにコピーし、TCPDFよりPDFを作成すればAcrobatReaderでもIllustratorでも問題なく開くことが出来るPDFファイルの完成です。

いまいち文章が推敲されていないのでまとめます。

TCPDFはPDF作成ライブラリですごい
TCPDFのPDFはOTFフォントを使うとIllustratorでは読めない(ラスタライズされる)ことがある
TCPDFのPDFをIllustratorで読む可能性があるならOTFフォントをTTFフォントに変換しておく
OTFフォントをTTFフォントに変換するにはFontForgeを利用する
CIDマップがないとOTFファイルを展開できない(ことがあるかもしれない)