LoginSignup
6
3

More than 5 years have passed since last update.

本当は怖いstr_replace(array, array, '...')

Last updated at Posted at 2016-12-06

PHPで単純な文字列置換をするときには、str_replace()という関数を使うのが定番ですが、実はこのstr_replace()には配列を指定して複数パターンを一括指定することができます。

$pattern = [
    'pattern1' => 'replacement1',
    'pattern2' => 'replacement2',
    'pattern3' => 'replacement3',
];

$str = str_replace(array_keys($pattern), array_values($pattern), '...');

ちょっとわかりづらいですが、第一引数にパターンの配列を、第二引数に置換後文字の配列を渡します。

同じような関数としてstrtr()という関数があります。
第2引数にパターンの配列を指定すると、複数パターンの一括置換ができます。

$pattern = [
    'pattern1' => 'replacement1',
    'pattern2' => 'replacement2',
    'pattern3' => 'replacement3',
];

$str = strtr('...', $pattern);

さて

これら処理は等価でしょうか?
次の例を見てみましょう。

$pattern = [
    'a' => 'b',
    'b' => 'c'
];

echo "str_replace(): " . str_replace(array_keys($pattern), array_values($pattern), 'ab') . "\n";
echo "strtr()      : " . strtr('ab', $pattern) . "\n";
結果
str_replace(): cc
strtr()      : bc

結果が異なりました。

str_replace()はパターンを順番に適用していくため、

$pattern = [
    'a' => 'b',
    'b' => 'c'
];

$str = 'ab';
foreach($pattern as $pattern => $replacement){
    $str = str_replace($pattern, $replacement, $str);
}

と等価な結果になります。(おそらく内部実装もそうなっていると思われます。)
その為、abbbccと置換されたことになります。

strtr()の場合は、置換済みの部分が再置換されることはありません。
内部実装としては文字列を先頭文字から順番にパターンマッチングして、マッチしたらその部分を置換していく処理になっているものと思われます。

まとめ

  • 文字列全体に置換パターンを適用したい場合 → str_replace()
  • 文字列に1回だけ置換パターンを適用したい場合 → strtr()

ただ、str_replace(array, array, '...')はわかりづらいので

foreach($pattern as $pattern => $replacement){
    $str = str_replace($pattern, $replacement, $str);
}

と書いたほうが無難だと思います。

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3