01 · THE IDEAREAD → TRY → LEARN
Why fixed-string replacement matters
Templates, log messages and generated text often contain placeholders such as {name} or %code%. When the placeholder is an exact piece of text rather than a pattern, str_replace() is the simplest tool. It searches for every occurrence of a needle and swaps each one for a replacement. It does not interpret regular expression syntax, so characters like . or * are just characters.
The signature is str_replace(array|string $search, array|string $replace, string|array $subject, int &$count = null): string|array. The matching is case-sensitive; str_ireplace() is the case-insensitive sibling.
The simple case
With strings for all three arguments, every occurrence is replaced, including ones hidden inside longer words. The optional fourth argument is passed by reference and receives the number of replacements made.
$text = str_replace('cat', 'dog', 'cat concat cat', $count);
echo json_encode([$text, $count], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;["dog condog dog",3]
Notice that concat became condog. The function has no notion of words, only of substrings. If you need word boundaries, you need a different approach such as a regular expression.
Arrays of needles
Pass an array as $search and an array as $replace to handle several tokens in one call. The first needle pairs with the first replacement, the second with the second, and so on. If the replacement array is shorter, the missing replacements are empty strings. If $replace is a single string, it is used for every needle.
$search = ['{name}', '{city}'];
$replace = ['Ada', 'Paris'];
echo str_replace($search, $replace, '{name} lives in {city}.'), PHP_EOL;Ada lives in Paris.
If $subject is an array, the operation is applied to each entry and an array is returned. That is useful, but this lesson focuses on string subjects.
The order gotcha
When you give arrays, PHP works through the pairs from first to last, and each pass operates on the result of the previous one. A value inserted by an earlier pair can therefore be matched by a later needle.
$search = ['A', 'B'];
$replace = ['B', 'C'];
$sequential = str_replace($search, $replace, 'AB');
$onePass = strtr('AB', ['A' => 'B', 'B' => 'C']);
echo json_encode([$sequential, $onePass], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;["CC","BC"]
The first A became B, and then every B became C, giving CC. strtr() with an array does not rescan text it has already replaced, so it gives BC. Choose str_replace() when sequential behaviour is acceptable, and strtr() when replacement values might contain other tokens.
Worked example: building a search list from a map
A map of names to values is easy to store, but str_replace() wants two parallel lists. A loop can wrap each key in delimiters and collect both lists.
function fillPercent(string $text, array $values): string
{
$search = [];
$replace = [];
foreach ($values as $name => $value) {
$search[] = '%' . $name . '%';
$replace[] = $value;
}
return str_replace($search, $replace, $text);
}
echo json_encode(fillPercent('Hi %name%, you have %n% new messages.', ['name' => 'Sam', 'n' => '3']), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;"Hi Sam, you have 3 new messages."
The lists stay aligned because both are appended to in the same iteration. If the map is empty, both lists are empty and the text comes back unchanged, which is a sensible result.
Exercise contract
Write render(string $template, array $values): string. Each key in $values names a token written in curly braces in the template, so key name matches {name}. Replace every occurrence of every known token with its string value. Tokens without a matching key must stay exactly as written. An empty string is a valid replacement value. The function returns the new string and prints nothing.
The tests check these cases: a basic token, a token that appears twice, an unknown token, an empty map, and an empty replacement value. Think about which of them would break a solution that forgets to add the braces, or one that handles only the first key.
Recap
str_replace()replaces every fixed substring, case-sensitively.- Array needles are applied left to right, and later needles can match earlier replacements.
- The optional
$countargument reports how many replacements happened. - Build parallel
$searchand$replacelists from a map with one loop. - Use
strtr()for one-pass replacement andpreg_replace()for patterns.
Functions · Arrays · Types
- Replace multiple tokens predictably
- Implement and test a deterministic PHP 8.4 function