Strings7 min readExamples run on PHP 8.5.10

str_replace()

Learn how PHP 8.4 str_replace() swaps fixed text in strings and arrays, how it counts replacements, and where its left-to-right behavior surprises people.

Signature

str_replace(array|string $search, array|string $replace, string|array $subject, int &$count = null): string|array

Purpose

str_replace() finds every occurrence of a fixed piece of text and substitutes another piece of text. It does no pattern matching. The needle is compared literally, byte for byte, and the match is case-sensitive. It suits template placeholders, removing unwanted characters, normalizing separators, or swapping known words. When you need patterns, use preg_replace(). When you need case-insensitive matching, use str_ireplace().

Signature

Parameters and defaults

  • $search: the needle. It can be one string or an array of needles.
  • $replace: the replacement. It can be one string or an array of replacements.
  • $subject: the haystack. It can be a string, or an array whose entries are each processed.
  • $count: optional, passed by reference. If you supply a variable, PHP stores the total number of replacements performed in it. Without it, no count is reported.

When $search and $replace are both arrays, the values are paired by position, first to last. If $replace has fewer entries than $search, the missing replacements are treated as empty strings. If $search is an array and $replace is a single string, that string is used for every needle. The reverse combination, a string needle with an array of replacements, makes no sense and is rejected with a TypeError.

Return value and failure cases

The function returns a string when $subject is a string, and an array when $subject is an array. In the array case the keys are preserved and each entry is replaced individually. The original subject is never modified; you must use the returned value. If nothing matches, you get an equivalent value back and the count is 0. An empty search string is not an error; it simply produces no replacement for that needle. Passing argument types the signature does not allow raises a TypeError.

Example 1: a basic replacement with a count

The count is the number of replacements, not the number of changed strings.

Example
<?php
$count = 0;
$result = str_replace("cat", "dog", "cat sat with a cat", $count);
echo json_encode(["result" => $result, "count" => $count], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"result":"dog sat with a dog","count":2}

Example 2: arrays of needles and the ordering effect

With array needles, PHP applies the pairs one after another to the result of the previous step. That means a value inserted by an earlier pair can be matched again by a later pair. In the first call below, A becomes B, then that B becomes C, then D. In the second call the replacement array is shorter, so b is replaced by an empty string.

Example
<?php
$search = ['A', 'B', 'C'];
$replace = ['B', 'C', 'D'];
echo str_replace($search, $replace, 'A'), PHP_EOL;
echo str_replace(['a', 'b'], ['1'], 'aabbc'), PHP_EOL;
Output
D
11c

Example 3: an array subject and case sensitivity

When the subject is an array, every entry is searched and the keys stay the same. The count is the total across all entries. Notice that Apple with a capital letter is left alone, because matching is case-sensitive.

Example
<?php
$items = ['name' => 'Red Apple', 'note' => 'red apple', 'other' => 'pear'];
$result = str_replace('apple', 'plum', $items, $count);
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
echo $count, PHP_EOL;
Output
{"name":"Red Apple","note":"red plum","other":"pear"}
1

Edge cases

  • Chained replacements. Because array pairs are applied in order, the output of one pair is the input of the next. Order your arrays deliberately. For example, when normalizing line endings, search for \r\n before \n and \r, so a Windows line break is not converted twice.
  • Overlapping needles. If one needle is a prefix of another, place the longer needle first, or the shorter one may consume part of it.
  • Counting. $count accumulates over every needle and every array entry, so it can be larger than the number of subject entries.
  • Binary safety. The function works on raw bytes, so it is safe for data containing null bytes. It does not understand multibyte characters; it only matches the exact byte sequence you give it.
  • No match. The subject comes back unchanged and $count is set to 0.

Common mistakes

  1. Ignoring the return value. Calling str_replace('a', 'b', $text); on its own statement changes nothing. Assign the result: $text = str_replace('a', 'b', $text);.
  2. Expecting case-insensitive matching. Apple and apple are different needles. Use str_ireplace() when case should not matter.
  3. Using it for patterns. Wildcards or character classes are treated as literal text. Use preg_replace() for those.
  4. Forgetting cascading. Swapping two words with str_replace(['a', 'b'], ['b', 'a'], $s) does not swap them: everything ends up as one letter. For a true simultaneous swap, strtr() with an array is the better tool.
  5. Passing an array of replacements for a string needle. This combination is invalid and throws a TypeError.
  6. Reading $count as a boolean. It holds a number of replacements, so compare it to 0 when you need to know whether anything changed.
  • str_ireplace(): the case-insensitive version.
  • substr_replace(): replaces text within a given position range.
  • preg_replace(): replaces by regular expression.
  • strtr(): translates characters or replaces substrings without re-scanning replaced text.

Recap

str_replace() performs literal, case-sensitive, left-to-right replacement on a string or on every entry of an array, and returns a new value of the same kind. Use the optional $count to learn how many replacements happened, keep the order of array pairs in mind, and reach for strtr(), str_ireplace() or preg_replace() when your needs go beyond a simple literal swap.

Tested examples

Basic replacement with a replacement count
<?php
$count = 0;
$result = str_replace("cat", "dog", "cat sat with a cat", $count);
echo json_encode(["result" => $result, "count" => $count], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"result":"dog sat with a dog","count":2}
Array needles, cascading replacement and short replacement array
<?php
$search = ['A', 'B', 'C'];
$replace = ['B', 'C', 'D'];
echo str_replace($search, $replace, 'A'), PHP_EOL;
echo str_replace(['a', 'b'], ['1'], 'aabbc'), PHP_EOL;
Output
D
11c
Array subject with case-sensitive matching
<?php
$items = ['name' => 'Red Apple', 'note' => 'red apple', 'other' => 'pear'];
$result = str_replace('apple', 'plum', $items, $count);
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
echo $count, PHP_EOL;
Output
{"name":"Red Apple","note":"red plum","other":"pear"}
1