Strings7 min readExamples run on PHP 8.5.10

soundex()

Learn how PHP 8.4 soundex() turns a word into a four-character phonetic key, how to compare names with it, and which edge cases and mistakes to avoid.

Signature

soundex(string $string): string

Purpose

soundex() converts a string into a short phonetic key. Words that sound alike in English tend to produce the same key, even if they are spelled differently. That makes it useful for rough name matching, such as finding Robert when a user typed Rupert, or grouping surnames that differ only by spelling.

PHP uses the variant described by Donald Knuth in The Art of Computer Programming, vol. 3. The result is not a similarity score. It is a code you compare for equality.

Signature

Parameters

  • $string: the input text. It has no default and is required. The function is designed for English letters. Characters that are not letters do not contribute to the key.

Return value and failure cases

The function always returns a string of four characters. If the input contains at least one letter, the key starts with a letter, followed by three digits, for example R163. If the input contains no letters at all, the result is "0000".

The key is built roughly like this: the first letter is kept, vowels and some other letters are dropped, the remaining consonants are mapped to digits so that similar-sounding consonants share a digit, adjacent repeats collapse, and the result is padded with zeros or cut to four characters.

There is no false return value in PHP 8. Before PHP 8.0.0, passing an empty string returned false; that no longer happens. A TypeError only appears if you pass a non-string where the type cannot be coerced, or you pass a non-string under declare(strict_types=1).

Example 1: basic keys

The function ignores letter case, so Robert and rupert give the same key. A string with no letters gives 0000.

Example
<?php
echo json_encode([soundex("Robert"), soundex("rupert"), soundex("123"), soundex("Lloyd")]), PHP_EOL;
Output
["R163","R163","0000","L300"]

Example 2: comparing names pairwise

The manual lists pairs such as Euler and Ellery or Knuth and Kant that share keys. Building a map from name to key makes the match visible.

Example
<?php
$names = ['Euler', 'Ellery', 'Knuth', 'Kant'];
$keys = [];
foreach ($names as $name) {
    $keys[$name] = soundex($name);
}
echo json_encode($keys), PHP_EOL;
Output
{"Euler":"E460","Ellery":"E460","Knuth":"K530","Kant":"K530"}

A realistic use is filtering a list of candidates by the key of a search term. Here Robert is compared to a list in memory; only names with the same key survive.

Example
<?php
function similarSounding(string $needle, array $candidates): array
{
    $target = soundex($needle);
    return array_values(array_filter(
        $candidates,
        fn(string $candidate): bool => soundex($candidate) === $target
    ));
}

echo json_encode(similarSounding('Robert', ['Rupert', 'Rubin', 'Robyn', 'Albert'])), PHP_EOL;
Output
["Rupert"]

Rubin and Robyn both start with R but produce R150, so they are not equal to R163. Albert starts with a different letter, so it never matches.

Edge cases

  • No letters: inputs such as "123" give "0000". Per the manual, the same holds whenever a string contains no letters. Treat "0000" as "no usable key", not as a real match between two unrelated inputs.
  • First letter matters: the key always begins with the first letter, so words that sound the same but start with different letters (for example, a silent first letter) get different keys.
  • Four characters only: long words are truncated, so very different long words can share a key. This makes soundex a coarse filter.
  • Case: upper and lower case produce the same key.
  • English focus: the algorithm models English pronunciation. Do not expect meaningful results for other languages or accented text.

Common mistakes

  1. Treating the key as unique. Many different words share one key. Use soundex to narrow candidates, then verify with another check.
  2. Comparing "0000" results. Two inputs without letters both return "0000" and compare equal. Check for letters first if that matters.
  3. Using loose comparison carelessly. Keys are strings; use === to compare them. Keys like "0000" can behave surprisingly with loose numeric-string comparison rules.
  4. Expecting a distance. soundex() says nothing about how close two words are. For an edit distance use levenshtein(); for percentage similarity use similar_text().
  5. Handling the old false result. Code written for PHP 7 that checks for false on empty input is obsolete in PHP 8.
  • metaphone(): another phonetic key, with a variable-length result.
  • levenshtein(): the number of edits between two strings.
  • similar_text(): counts matching characters and can report a percentage.

Recap

soundex(string $string): string returns a four-character phonetic key. Equal keys suggest similar English pronunciation, case is ignored, and strings without letters give "0000". Use it as a quick, approximate filter and combine it with stricter checks when accuracy matters.

Tested examples

Basic keys, case insensitivity and no-letter input
<?php
echo json_encode([soundex("Robert"), soundex("rupert"), soundex("123"), soundex("Lloyd")]), PHP_EOL;
Output
["R163","R163","0000","L300"]
Comparing names pairwise
<?php
$names = ['Euler', 'Ellery', 'Knuth', 'Kant'];
$keys = [];
foreach ($names as $name) {
    $keys[$name] = soundex($name);
}
echo json_encode($keys), PHP_EOL;
Output
{"Euler":"E460","Ellery":"E460","Knuth":"K530","Kant":"K530"}
A small phonetic search
<?php
function similarSounding(string $needle, array $candidates): array
{
    $target = soundex($needle);
    return array_values(array_filter(
        $candidates,
        fn(string $candidate): bool => soundex($candidate) === $target
    ));
}

echo json_encode(similarSounding('Robert', ['Rupert', 'Rubin', 'Robyn', 'Albert'])), PHP_EOL;
Output
["Rupert"]