Strings7 min readExamples run on PHP 8.5.10

strtr()

Learn how PHP 8.4 strtr() works in its two forms: byte-by-byte translation and longest-match array replacement. Includes examples, edge cases and mistakes.

Signature

strtr(string $string, string $from, string $to): string
strtr(string $string, array $replace_pairs): string

Purpose

strtr() rewrites a string using a lookup table. It has two quite different modes. With three string arguments it maps single bytes to other single bytes. With a string and an array it replaces whole substrings, trying the longest keys first and never rescanning text it has just inserted. The second mode is a good fit for templates, escape tables and swapping two words in one pass.

Signature

The array form is documented as an alternative signature and is not supported with named arguments, so pass its arguments positionally.

Parameters

  • $string: the input. It is not modified; a new string is returned.
  • $from and $to (three-argument form): $from[$n] is replaced by $to[$n]. If the two strings differ in length, the extra characters of the longer one are ignored.
  • $replace_pairs (two-argument form): an array of the form ['search' => 'replacement']. Keys and values may have any length, but a key must not be an empty string.

There are no optional parameters. The form you get depends on how many arguments you pass.

Return value and failures

The function always returns a string. In the three-argument form the result has the same length as the input. In the array form the length can change. An empty-string key is ignored, and since PHP 8.0 it also raises an E_WARNING. Passing the wrong argument types for the chosen form, such as an array together with a third argument, is a type error rather than a silent fallback.

Example 1: byte translation

The first call fixes the characters 1, L and 0 by mapping them to l, l and o. The second call shows that a shorter $to simply leaves the unmatched bytes alone.

Example
<?php
echo strtr("He1Lo, w0rld!", "1L0", "llo"), "\n";
echo strtr("abcabc", "abc", "xy"), "\n";
Output
Hello, world!
xycxyc

Because c has no partner in $to, it stays as it is.

Example 2: filling a template

The array form is a compact placeholder engine. Placeholders without an entry in the table are left untouched.

Example
<?php
$template = "Hello {name}, your order {id} is ready. {unknown}";
$result = strtr($template, ["{name}" => "Ada", "{id}" => "#42"]);
echo $result, "\n";
Output
Hello Ada, your order #42 is ready. {unknown}

Example 3: swapping and comparing modes

Because replaced text is never searched again, strtr() can swap two words correctly. Sequential str_replace() cannot, since the second pass sees the output of the first. The last two lines contrast the byte mode with the substring mode.

Example
<?php
echo strtr("cat and dog", ["cat" => "dog", "dog" => "cat"]), "\n";
echo str_replace(["cat", "dog"], ["dog", "cat"], "cat and dog"), "\n";
echo strtr("baab", "ab", "01"), "\n";
echo strtr("baab", ["ab" => "01"]), "\n";
Output
dog and cat
cat and cat
1001
ba01

The three-argument call turns every a into 0 and every b into 1. The array call replaces only the exact sequence ab, which occurs once.

Edge cases

  • Longest key wins. With keys h, hi and hello, the input hello is matched by hello, not by h. Order in the array does not decide this.
  • No rescanning. Once a substring has been replaced, its replacement is not examined again, so chained or circular mappings do not cascade.
  • Case sensitivity. Matching is exact. Cat and cat are different keys.
  • Multibyte text. The three-argument form works on bytes. Translating Ä (two bytes in UTF-8) with strtr($s, 'Ä', 'A') changes only the first byte and leaves a broken sequence. Use the array form for multibyte characters, which matches whole byte sequences.
  • Efficiency. The array form is fastest when all keys have the same length.
  • Empty keys. They are skipped and trigger a warning in PHP 8.

Common mistakes

  1. Using the three-argument form to replace words. It maps individual characters, so strtr($s, "cat", "dog") converts every c, a and t anywhere in the string, not the word cat.
  2. Assuming $from and $to must have equal lengths. Unequal lengths do not fail; the surplus is silently dropped, which can hide a typo.
  3. Expecting the order of the array to set priority. Length of the key decides, not position.
  4. Chaining several str_replace() calls for a swap and getting double replacements.
  5. Using the byte form on UTF-8 text and corrupting characters.
  6. Building the table from untrusted data without checking for empty keys.
  • str_replace() replaces occurrences sequentially, with optional arrays of searches and replacements.
  • preg_replace() handles pattern-based replacement when fixed strings are not enough.

Recap

Use strtr($string, $from, $to) for single-byte mapping and strtr($string, $pairs) for substring replacement. The array form prefers the longest match, never rescans inserted text, and is the right tool for placeholder tables and safe swaps. Keep multibyte text out of the byte form.

Tested examples

Byte translation and mismatched lengths
<?php
echo strtr("He1Lo, w0rld!", "1L0", "llo"), "\n";
echo strtr("abcabc", "abc", "xy"), "\n";
Output
Hello, world!
xycxyc
Filling a template with an array
<?php
$template = "Hello {name}, your order {id} is ready. {unknown}";
$result = strtr($template, ["{name}" => "Ada", "{id}" => "#42"]);
echo $result, "\n";
Output
Hello Ada, your order #42 is ready. {unknown}
Swapping words and comparing the two modes
<?php
echo strtr("cat and dog", ["cat" => "dog", "dog" => "cat"]), "\n";
echo str_replace(["cat", "dog"], ["dog", "cat"], "cat and dog"), "\n";
echo strtr("baab", "ab", "01"), "\n";
echo strtr("baab", ["ab" => "01"]), "\n";
Output
dog and cat
cat and cat
1001
ba01