マルチバイトを考慮したstr_replace関数

category-icon

 こんばんは。最近、めっきり寒くなってきました。ラボは基本的に中央暖房なんですが、古いせいか壊れていて温度計は14度ぐらい。冷え症の身には応えます。

 さて、ユーザーの方から、パスワードやIDを変更したタイミングでログが壊れるという報告がありました。こちらでは再現出来なかったんですが、調べたところ、ログの書き換えにマルチバイトに対応していないstr_replace関数を使っているのが原因かと思いますので、マルチバイトに対応したやつを考えてみました。PHPには、マルチバイトに対応した色んな関数が揃っているLink のですが、頻用する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()関数界隈が変わっています。

添付ファイル: utilsadmin.phpattachedIcon 

— posted by martin at 05:19 am   commentComment [0]  pingTrackBack [0]

この記事に対する TrackBack URL:

設定によりTB元のページに、こちらの記事への言及(この記事へのリンク)がなければ、TB受付不可となりますのであらかじめご了承下さい。

コメントをどうぞ。 名前(ペンネーム)と画像認証のひらがな4文字は必須で、ウェブサイトURLはオプションです。

ウェブサイト (U):

タグは使えません。http://・・・ は自動的にリンク表示となります

:) :D 8-) ;-) :P :E :o :( (TT) ):T (--) (++!) ?;w) (-o-) (**!) ;v) f(--; :B l_P~

     
T: Y: ALL: Online:
Created in 0.0288 sec.
prev
2017.12
next
          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