こんばんは。最近、めっきり寒くなってきました。ラボは基本的に中央暖房なんですが、古いせいか壊れていて温度計は14度ぐらい。冷え症の身には応えます。
さて、ユーザーの方から、パスワードやIDを変更したタイミングでログが壊れるという報告がありました。こちらでは再現出来なかったんですが、調べたところ、ログの書き換えにマルチバイトに対応していないstr_replace関数を使っているのが原因かと思いますので、マルチバイトに対応したやつを考えてみました。PHPには、マルチバイトに対応した色んな関数が揃っている のですが、頻用するstr_replaceのマルチバイト版mb_str_replaceが(何故か)ありません。オンラインのPHPマニュアルには、ユーザー寄稿のメモが沢山載せてあって、色々と参考になります。この中に、mb_str_replace()があったので、それに若干修正を加えて以下のようなものを用意しました。
/* マルチバイトを考慮したstr_replace */ function my_str_replace($search, $replace, $target, $encoding = ENCODE){ $notArray = !is_array($target) ? TRUE : FALSE; $target = $notArray ? array($target) : $target; $search_len = mb_strlen($search, $encoding); $replace_len = mb_strlen($replace, $encoding); foreach ($target as $i => $tar){ $offset = mb_strpos($tar, $search); while ($offset !== FALSE){ $tar = mb_substr($tar, 0, $offset).$replace.mb_substr($tar, $offset + $search_len); $offset = mb_strpos($tar, $search, $offset + $replace_len); } $target[$i] = $tar; } return $notArray ? $target[0] : $target; }
これで、str_replace関数と大体似たような挙動をしてくれますが、本家str_replaceと違う点は、引数(ひきすう)の$searchや$replaceに配列を指定出来ないことです。なので配列に対応した関数を用意しましょう。上記の関数を使います。
/* str_replace関数のマルチバイト版 上記 my_str_replace()が必要 */ function mb_str_replace($search, $replace, $target){ if(is_array($search)){ // $searchが配列なら if(!is_array($replace)) $replace = array($replace); foreach ($search as $i => $needle){ $rep = isset($replace[$i]) ? $replace[$i] : $replace[0]; $target = my_str_replace($needle, $rep, $target); } return $target; } else return my_str_replace($search, $replace, $target); // $searchが配列でないとき }
これを使ったサンプルをば。全角空白を□(四角)に、「空白」という文字を「四角」に置換します。
$target = " おか機 ←全角空白です。"; $search = array(' ', '空白'); $replace = array('□', '四角'); $result = mb_str_replace($search, $replace, $target); var_dump($result); // これで結果を出力
これの結果は、以下の通り。パフォーマンスもそんなに悪くないと思います。
string(39) "□おか機□←全角四角です。"
これの修正を施したutils_admin.phpの最新版を添付しておきます。replace_log_by_target()関数界隈が変わっています。
Comments