So what happens here?
$text = " a b c ";
$text = strtr($text, array(" a " => " b ", " b " => " a ", " c " => " d "));
First you have to know that:
- The longest keys will be replaced first
- After it got replaced it doesn't search for this key anymore
So here all keys have the same length, means it will replace the first key => value
element, then the second and so on.
So first " a " => " b "
will be replaced, which will change your start string:
a b c
↑↑↑ Match
to this:
b b c
↑↑↑ Replacement
Remember how we said, after replacing the values it doesn't search for it anymore? Exactly! Now it searches for " b " => " a "
, but only in this part of the string:
a b c
So it won't find it, since there is no space in front of the b to search for. That's why you don't get your expected output. And c
will be found again, since it has a space in front of it.
So the problem here in your code is, that it doesn't include replaced values in the search of the next key. Even if [space]b[space]
is in your string, it doesn't find it, since the first space is from the replaced value of the key [space]a[space]
, which won't be included in the next search.
EDIT:
As from your updated question it seems that you have done this to try to prevent words be part of other words. To solve this simply make a lookup array and use preg_replace_callback()
with word boundarys to match only full words and not only a part of it, e.g.
<?php
$text = " apple bacon cats ";
$replacement = ["apple" => "bacon", "bacon" => "apple", "cats" => "dogs"];
$search = array_map(function($v){
return preg_quote($v, "/");
}, array_keys($replacement));
echo $text = preg_replace_callback("/\b(" . implode("|", $search) . ")\b/", function($m)use($replacement){
return $replacement[$m[1]];
}, $text);
?>