こんばんは。最近、めっきり寒くなってきました。ラボは基本的に中央暖房なんですが、古いせいか壊れていて温度計は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