7

I need to replace multiple value using str_replace.

This is my PHP code fore replace.

$date = str_replace(
       array('y', 'm', 'd', 'h', 'i', 's'),
       array('Year', 'Month', 'Days', 'Hours', 'Munites', 'Seconds'),
       $key
    );

When i pass m in $key it return output like.

MontHours

When i pass h in $key it return output.

HourSeconds

it return this value i want the Month only.

Renish Khunt
  • 5,620
  • 18
  • 55
  • 92
  • show us how your using it, seems like your using it again after it's been used.. ie m becomes month then you run it again month become monthours because the h in month. – Bryan Mar 22 '14 at 08:11
  • or it's looping to do the replace, not 100% the implementation of str_replace, but rearranging the order of the letter in the first array can probably fix this. – Bryan Mar 22 '14 at 08:13

3 Answers3

9

Why doesn't it work?

This is a replacement gotcha which is mentioned in the documentation for str_replace():

Replacement order gotcha

Because str_replace() replaces left to right, it might replace a previously inserted value when doing multiple replacements. See also the examples in this document.

Your code is equivalent to:

$key = 'm';

$key = str_replace('y', 'Year', $key);
$key = str_replace('m', 'Month', $key);
$key = str_replace('d', 'Days', $key);
$key = str_replace('h', 'Hours', $key);
$key = str_replace('i', 'Munites', $key);
$key = str_replace('s', 'Seconds', $key);

echo $key;

As you can see m gets replaced with Month, and h in Month gets replaced with Hours and the s in Hours gets replaced with Seconds. The problem is that when you're replacing h in Month, you're doing it regardless of whether the string Month represents what was originally Month or what was originally an m. Each str_replace() is discarding some information — what the original string was.

This is how you got that result:

0) y -> Year
Replacement: none

1) m -> Month
Replacement: m -> Month

2) d -> Days
Replacement: none

3) h -> Hours
Replacement: Month -> MontHours

4) i -> Munites
Replacement: none

5) s -> Seconds
Replacement: MontHours -> MontHourSeconds

The solution

The solution would be to use strtr() because it won't change already replaced characters.

$key = 'm';
$search = array('y', 'm', 'd', 'h', 'i', 's');
$replace = array('Year', 'Month', 'Days', 'Hours', 'Munites', 'Seconds');

$replacePairs = array_combine($search, $replace);
echo strtr($key, $replacePairs); // => Month
Amal Murali
  • 75,622
  • 18
  • 128
  • 150
6

From the manual page for str_replace():

Caution

Replacement order gotcha

Because str_replace() replaces left to right, it might replace a previously inserted value when doing multiple replacements. See also the examples in this document.

For example, "m" is replaced with "Month", then the "h" in "Month" is replaced with "Hours", which comes later in the array of replacements.

strtr() doesn't have this issue because it tries all keys of the same length at the same time:

$date = strtr($key, array(
    'y' => 'Year',
    'm' => 'Month',
    'd' => 'Days',
    'h' => 'Hours',
    'i' => 'Munites', // [sic]
    's' => 'Seconds',
));
PleaseStand
  • 31,641
  • 6
  • 68
  • 95
-1

A simpler fix is to change the search order:

array('Year', 'Seconds', 'Hours', 'Month', 'Days', 'Minutes')

str_replace and preg_replace will both search for each search item one at a time. Any multi-value will need to make sure the order doesn't change a previous replace item.

Nana Partykar
  • 10,556
  • 10
  • 48
  • 77
Humanoid1000
  • 155
  • 2
  • 9