Lesson 34 of 100
Strings15 min5 checksPHP 8.5

Replace Text with str_replace

Learn how str_replace swaps fixed substrings, handles arrays of tokens, counts replacements, and why replacement order matters.

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.

Example
<?php
$text = str_replace('cat', 'dog', 'cat concat cat', $count);
echo json_encode([$text, $count], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
["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.

Example
<?php
$search = ['{name}', '{city}'];
$replace = ['Ada', 'Paris'];
echo str_replace($search, $replace, '{name} lives in {city}.'), PHP_EOL;
Output
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.

Example
<?php
$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;
Output
["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.

Example
<?php
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;
Output
"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 $count argument reports how many replacements happened.
  • Build parallel $search and $replace lists from a map with one loop.
  • Use strtr() for one-pass replacement and preg_replace() for patterns.
Before you start

Functions · Arrays · Types

You’ll practice
  • Replace multiple tokens predictably
  • Implement and test a deterministic PHP 8.4 function
Your task

Make render() pass all 5 checks. Run your code as often as you like, then check your answer.

exercise.phpSaved in this browserPHP 8.5
CONSOLE & CHECKS● Ready

Ready when you are

Your output will appear here.
Make it work. Then make it pass.

PHP loads on your first run. Each check starts fresh. Your code stays in this browser; clearing site data removes your progress. A check or the task looks wrong? Report a problem with this exercise.