Tagged ‘PHP’

文字コードで気をつけること

multibyte

よく「JIS(ISO-2022-JP)」と表現されますが、PHPでは「ISO-2022-JP」と「JIS」は違う文字コードになります。
「ISO-2022-JP」はメールでよく使われる文字コードで規格を厳守してるので機種依存文字(ISO-2022-JP規定外文字)や半角カナ共に扱えません。
一方「JIS」は半角カナが使え、機種依存文字が扱えない。
八方ふさがりのように見えるがPHP5.2.1からは「ISO-2022-JP-MS」が用意されており、コレだと機種依存文字も半角カナも扱える。
「メールはJISだから機種依存文字や半角カナが送信出来ない」はずだが、ISO-2022-JPのふりして中身をISO-2022-JP-MSにすると機種依存文字が送れたりします。(受け手のメールソフトが対応してた場合のみですが・・・)
(さらに…)

simplexml_load_fileとsimplexml_load_stringの速度比較

xmlspeed_s

外部サイトのRSSを読む処理をする際に専用の関数simplexml_load_fileを使っていた。
混雑するサイトを考慮してタイムアウト時間、待機時間、再試行回数を含めた関数を作った。
(さらに…)

コンストラクタで多言語化を

PHPなどのシステムで多言語に対応する際は出力の度に言語で分岐して出力するより、言語ファイルを用意した方が効率的です。

言語ファイルと言えばプログラム業界では「.po」「.mo」といったファイルがよく見られます。(はてなの場合
これらの言語ファイルをPHPで使うには下記の流れの作業する事になります。

1. 翻訳元の「.pot」ファイルを作成
2. ファイルを元に翻訳元と翻訳後の書かれた「.po」ファイルを作成
3. 「.po」ファイルを「.mo」ファイルにバイナリ変換
4. GetTextというライブラリで翻訳させる。

大規模なシステムだと分業しやすいというメリットはありますが「TASK4BOX」みたいな規模の小さいシステムだと大袈裟なので自前で言語ファイルを作る事にした。
(さらに…)

iPhoneに元号アイコン

元号アイコン
WEBは西暦表記が多いですが書類を書いたりする際には未だ元号(年号)で記入する事が多々あります。
Siriに「今年は平成何年?」と聞いたらも答えてくれますが恥ずかしいです。
IT4コマ漫画:今って平成何年だっけ? – ITmedia ニュース
によるとそういうアプリがあるとの事ですが年号がバッジ(右上の数字)で表現されていて見た目が微妙です。
そこで、巷にあるアイコンをカスタムするアプリの方法を使って元号の書かれたアイコンを貼れないか試してみた。
(さらに…)

○○で始まる文字列検索の速度比較

PHPにて「○○で始まる文字列」を検索する場合、一番に思いつくのは正規表現だけど重いのでstrposで検索していたがstrposは検索位置を返すし全体を検索するのでなんとなく遅いかなと思い別の方法を模索してみた。

PHPのパフォーマンス改善(3) | Selfkleptomaniac
という記事にstrncmpを含んだ3つの方法が書かれていたので計5つの方法のベンチを取って比較してみた。
(各秒数は約8万行を検索したしたベンチの10回分の平均値。)

strncmp版(先頭から特定文字数分検索する関数)
if (!strncmp($myvalue, $searchstr, 5)) ~
0.0312 sec

substr版(文字列を部分抽出する関数)
if (substr($myvalue, 0, 5) == $searchstr) ~
0.0447 sec

preg_match版(正規表現を利用した検索)
if (preg_match(‘!^’.$searchstr.’!’, $myvalue)) ~
0.0578 sec

substr_compare版(特定部分から特定文字数分検索する関数)
if (substr_compare($myvalue, $searchstr, 0, 5) == 0) ~
0.0415 sec

strpos版(文字列の開始位置を検索する関数)
if (strpos($myvalue, $searchstr) === 0) ~
0.0297 sec

おっしゃる通り「strncmp」は速く「preg_match」は遅いが「strpos」が予想以上に速く、単純な文字列の検索も今回のような特定位置の文字列検索も「strpos」が最速という結果になった。

PHPの高速化

MyReleaseの新規セッションの割合が低下していた。
Yahoo!が検索エンジンをGoogleの検索エンジンに切り替えた為だ。

そこで、PHPの高速化をとスクリプトを調整していたが限界が来たのでサーバーの設定を変更することにしました。
とりあえず「eAccelerator」を入れてみた。
MyReleaseはCPIのVPSで元々PHP4でPleskという環境に、無理やりPHP5を導入してるので不安だったが何の問題もなくインストールできた。体感できるほど速くはならなかったがコンパネから利用状況が分かり頑張ってる様子がわかる。

次に「eAccelerator」と同居できるという事で「ZendOptimizer」もインストールした。
これは入会する手間はあるが簡単にインストールできた。
ただ、バージョンが3.3.9と新しく色んなサイトで紹介されてるインストーラーを使ったインストールができないが、必要なファイルをコピーしてphp.iniにコピーした場所を記述するだけでOKという簡単な作業でインストール完了。

更にmySQLのインデックスも微調整した。query_cacheを調整したりすると、ようやく体感できるレベルに改善された。

このおかげかは分からないけどランキングは約一年ぶりに5位に戻った。

PHPで複数のURLを404チェックする関数の速度比較

amazonのAPIなんかを利用して画像のパスを取得し保存していると稀に画像が削除されてしまってる事がある。
毎回、amazonのAPIを叩く様にしてもいいかもしれないけど頻繁にアクセスするとamazonに怒られるかもしれない。
そこで、ファイルが存在するかチェックする事にしたのだけどPHPには色々関数があるのでそれぞれチェックしてみた。
(さらに…)

マルチバイト文字のtrim

yahoo!の検索エンジンがGooleの検索エンジンになるというニュースはありましたが
とうとう切り替わったのを確認してしまいました。(徐々に切り替わっていくらしい)

Googleはページの表示スピードも見てるらしいので少しでもPHPのスピードを上げたくて最近ではベンチを使って速度を比較している。
他者の計ったベンチがGoogleで調べればすぐに出てくるのになぜ自分で調べるかというと、例えば文字の置換はstr_replaceを使い。
$str = str_replase(“AAA”, “BBB”, $str);
とするが普通で速度も早いが、検索文字(例の場合”AAA”)の出現がレアな場合
if (strpos($str,”AAA”) !== false) $str = str_replase(“AAA”, “BBB”, $str);
と置換する前に先に検索した方が早かったりするので、実際のデータが無いと分からないのでベンチを計る必要が出てきたりする。

そんな中、比較的遅いというmb_ereg_replaceを使ってるマルチバイトのtrimを調査してみることにした。
$str = mb_ereg_replace(“^[  ]+”, “”, $str);
$str = mb_ereg_replace(“[  ]+$”, “”, $str);
昔、Shift-JISで単純にtrimの第2引数に全角スペースを入れてトリムすると文字化けしたのでmb_ereg_replaceを使ってるが、安全だけど遅い。
そこで昔文字化けした理由を調べに文字コードをwikipediaで見てみた。
Shift_JIS
第1バイトが81-9FとE0-FC、
第2バイトが40-7Eと80-FC
EUC-JP
第1バイトがA1-A8とADとB0-F4とF9-FC、(亜種は8FとF5-FEも)
第2バイトがA1-FE(亜種は第3バイトにもA1-FE)
UTF-8
第1バイトがC2-FD、
第2バイト以降が80-BF
trimのデフォルトの第2引数は
” ” (0x20), 半角スペース
“\t” (0x09), タブ
“\n” (0x0A), 改行
“\r” (0x0D), 復帰
“\0” (0x00), NUL バイト
“\x0B” (0x0B), 垂直タブ
とどの文字コードにも危険なコードが含まれていないので普通に使える。
ただtrimはマルチバイトには対応していないのでシングルバイトに変換され削除されるので全角スペースを除去しようとすると下記のように問題が発生する。
Shift_JISの全角スペースは0x8140でtrimの第2引数に全角スペースを入れると81と40が削られアウト
(http://charset.7jp.net/sjis.htmlの81と40が絡む行や列が文字化けする。)
EUC-JPの全角スペースは0xA1A1でtrimの第2引数に全角スペースを入れるとA1が削られアウト
(http://charset.7jp.net/euc.htmlのA1が絡む行や列が文字化けする。)
UTF-8の全角スペースは0xE38080でtrimの第2引数に全角スペースを入れるとE3と80が削られアウト

正しく全角スペースをトリムするならmb_ereg_replaceしか無く、すべての全角スペースが半角スペースになってもよければ
$str = trim(str_replase(“ ”, ” “, $str));
と先に全角スペースを半角スペースに変換するなど、シチュエーションによって使い分けるしか無いようだ。

新楽天ブックス系API

今日も暇だったのでメールの整理をしていたら「【重要】旧楽天ブックス系APIの廃止のお知らせと移行のお願い(楽天ウェブサービス)」のメールが・・・
後で見ようとマークを付けていた様だけどすっかり忘れてしまってた。日付を見ると5月25日。一ヶ月以上前のメールだ。
新楽天ブックス系APIはISBNやJANに対応してるらしい。
旧楽天ブックス系APIを使ったコンテンツを作った事があるがamazonとかのAPIと比べ劣っていたので出来るコンテンツが限られていたけど今回のは使えそうだ。
MyReleaseに新楽天ブックス系APIを付けてみた。
提供してくれる情報も豊富で書名や著者のフリガナまで付いてる。
テストで適当なISBNコードを入れてやってみた。返ってきたXMLを見ると名前にコロンが付いてる。XML名前空間ってやつだ。(名前空間の使い道はよくわかってない)
確かsimplexmlでは対応してなかったような・・・PHP4の時使ってたDOMの方ならなんとかなった気がするが面倒いなとか思いつつググってみると
楽天 API と simplexml_load_file : やおよろグッ!に解決方法が載ってた。
先にファイルを読み込んでセミコロンの部分を取り除いてからsimplexmlって方法。
裏技的な方法だけど問題なさそうなのでやってみた。
他の箇所も調整してたので時間は掛かったけど問題なく動いてる。
めでたしめでたし。と思ってると
SimpleXMLで名前空間付きタグの一覧を取得する – 肉とご飯と甘いもの @ sotarok
simplexmlでもやりようはあるみたい。

DNRH-001にVINE モジュール

仮サーバーの環境を本サーバーに近いように弄ってるとdomxmlが無いことに気づいた、結構使ってたのでPHPに標準で付いてる関数かと思ってた、検索してみるとモジュールを追加しなくてはいけないらしい。ダウンロードしてコンパイルみたいな事書いてたので面倒だなと思ってるとMLogの記事を発見、PHPのモジュールもソフトみたいにapt-getでインストールできる様だ。

# rpm -qa|grep php

でインストールされてるアプリからPHPを含むのを見てみる、当然だがそれっぽいのは無い。

# apt-get update

念のため最新版チェック

# apt-get install php-domxml

domxmlをインストール

# service apache2 reload

サーバーの再起動

# rpm -qa|grep php

でインストールされてる事を確認して

# php -r 'var_dump(function_exists("domxml_open_file"));'

domxmlの関数が使えるかチェック

ついでにphpMyAdminがmcryptを使ってるらしく下の方にアラートが出てたので

# apt-get install php-mcrypt

ってしてインストールした。
依存性の関係でlibmcryptも自動でインストールしてくれた。

あと、PEARにMailパッケージが入ってなかったので入れる。

# pear install -a Mail

ついでにアップデートもしとく

# pear upgrade-all
# pear update-channels