PHP tiene varias funciones para medir cuánto se parecen dos cadenas. Cada una usa un algoritmo diferente y sirve para casos de uso distintos: similar_text() mide caracteres en común, levenshtein() cuenta operaciones de edición, y soundex() y metaphone() comparan la pronunciación aproximada. Son la base de cualquier buscador tolerante a errores tipográficos.
similar_text(): porcentaje de similitud
<?php similar_text(string $string1, string $string2, float &$percent = null): int ?>
Devuelve el número de caracteres en común. Si le pasas una variable como tercer argumento, la rellena con el porcentaje de similitud:
<?php
similar_text('PHP', 'PHP', $p);
echo round($p, 1) . '%'; // 100%
similar_text('cadena', 'cadenas', $p);
echo round($p, 1) . '%'; // 92.3%
similar_text('gato', 'perro', $p);
echo round($p, 1) . '%'; // 22.2%
?>
levenshtein(): distancia de edición
La distancia de Levenshtein es el número mínimo de operaciones de inserción, eliminación o sustitución necesarias para transformar una cadena en otra. Cuanto menor es el valor, más parecidas son:
<?php
echo levenshtein('color', 'colour'); // 1 (inserción de 'u')
echo levenshtein('kitten', 'sitting'); // 3
echo levenshtein('noche', 'niche'); // 2
echo levenshtein('php', 'PHP'); // 3 (es case-sensitive)
?>
Buscador tolerante a errores tipográficos
<?php
$catalogo = ['zapatillas', 'camiseta', 'pantalón', 'chaqueta', 'bufanda'];
function buscarAproximado(string $termino, array $catalogo, int $maxDistancia = 2): array
{
$resultados = [];
foreach ($catalogo as $producto) {
$dist = levenshtein(strtolower($termino), strtolower($producto));
if ($dist <= $maxDistancia) {
$resultados[] = ['producto' => $producto, 'distancia' => $dist];
}
}
usort($resultados, fn($a, $b) => $a['distancia'] - $b['distancia']);
return array_column($resultados, 'producto');
}
// El usuario escribió "zapatila" (sin una l)
print_r(buscarAproximado('zapatila', $catalogo));
// Array ( [0] => zapatillas )
print_r(buscarAproximado('camizeta', $catalogo));
// Array ( [0] => camiseta )
?>
soundex() y metaphone(): comparación fonética
Ambas funciones codifican una cadena según su sonido aproximado en inglés. Sirven para detectar nombres propios mal escritos fonéticamente:
<?php
// soundex: código de 1 letra + 3 dígitos
echo soundex('Smith'); // S530
echo soundex('Smythe'); // S530 (suenan igual)
// metaphone: más preciso que soundex
echo metaphone('Garcia'); // KRSJ
echo metaphone('Garsia'); // KRSJ (mismo resultado)
// Comparación fonética
function sonanIgual(string $a, string $b): bool
{
return metaphone($a) === metaphone($b);
}
var_dump(sonanIgual('Catherine', 'Katherine')); // bool(true)
var_dump(sonanIgual('Juan', 'Wan')); // bool(true) en inglés
?>
Cuándo usar cada función y su rendimiento
levenshtein() es la más precisa para errores de escritura, pero tiene coste O(n×m) donde n y m son las longitudes de las cadenas. Para catálogos grandes, precalcula las distancias o usa índices de búsqueda de texto completo (como los de Elasticsearch o el FULLTEXT de MySQL) en lugar de comparar cadena a cadena en PHP.
similar_text() tiene un coste similar pero su algoritmo no es simétrico: similar_text('A', 'B') puede dar un porcentaje diferente a similar_text('B', 'A'). Para comparaciones de similitud consistentes normaliza el orden o usa Levenshtein.
Las funciones fonéticas (soundex, metaphone) están diseñadas para nombres propios en inglés. Funcionan mal con palabras en castellano porque las reglas de pronunciación son distintas.
La documentación oficial de similar_text() y la de levenshtein() incluyen las limitaciones de longitud y las notas de rendimiento.
