substr($string, $offset, $length) devuelve la parte de $string que empieza en la posición $offset (contando desde 0) y tiene $length caracteres. substr('Hello world', 0, 5) devuelve "Hello". Omite $length para obtener todo hasta el final.
substr() cuenta bytes. Eso equivale a caracteres en texto en inglés, pero no en japonés, chino, emojis o letras con tilde. Para esos casos usa mb_substr(), que se muestra más abajo.
Sintaxis
substr(string $string, int $offset, ?int $length = null): string
$offsetes dónde empezar.0es el primer carácter. Un valor negativo cuenta desde el final.$lengthes cuántos bytes tomar (un byte es un carácter en texto ASCII simple). Un valor negativo deja fuera esa cantidad del final.null(u omitirlo) significa "hasta el final".
Desplazamiento y longitud negativos: trabajar desde el final
Un $offset negativo empieza a contar desde el final de la cadena, así que -1 es el último carácter. Un $length negativo se detiene esa cantidad de caracteres antes del final.
substr($s, 0, -1) es la forma habitual de quitar el último carácter, por ejemplo una coma final que dejó un bucle.
Obtener el primer o el último carácter
Para un solo byte también puedes indexar la cadena directamente. $s[0] es el primer carácter y, desde PHP 7.1, $s[-1] es el último.
Indexar una posición que no existe imprime un warning, mientras que substr() simplemente devuelve una cadena vacía. Si la cadena puede estar vacía, prefiere substr().
Fuera de rango: una cadena vacía, no false
Si $offset está más allá del final de la cadena, substr() devuelve "" en PHP 8. En PHP 7 devolvía false, así que el código antiguo que comprueba === false ya no funciona.
Texto japonés: usa mb_substr
UTF-8 guarda los kana y los kanji comunes en 3 bytes cada uno (los kanji raros como 𠮷 y los emojis ocupan 4). substr() cuenta bytes, así que substr('こんにちは', 0, 3) devuelve solo こ, y una longitud que no cae en un límite de carácter parte un carácter por la mitad y produce texto roto. mb_substr() acepta los mismos argumentos y cuenta caracteres.
Lo mismo se aplica a los emojis y a las letras con tilde como é. Para contar caracteres se usa mb_strlen(); consulta strlen() para la diferencia entre bytes y caracteres.
Acortar texto con puntos suspensivos
Recortar un título largo para una lista o una tarjeta es el uso real más común de substr(). Usa mb_substr() para que un título en japonés nunca se corte a mitad de carácter, y añade ... solo cuando realmente hayas acortado algo.
mb_strimwidth($text, 0, $width, '...') hace lo mismo según el ancho de visualización, donde un carácter japonés de ancho completo cuenta como 2 columnas y una letra latina como 1. Encaja con diseños de ancho fijo.
Contar una subcadena con substr_count
substr_count($haystack, $needle) devuelve cuántas veces aparece $needle. Distingue mayúsculas y minúsculas y no cuenta coincidencias solapadas.
substr con strpos: el texto antes o después de un carácter
Combina substr() con strpos() para cortar en un carácter cuya posición no conoces de antemano, como la @ de una dirección de email:
Comprueba que strpos() no devolvió false antes de usar su resultado: si el carácter no está, false se trata como 0 sin ningún warning, así que substr('nobody', 0, $at) devuelve "" y substr('nobody', $at + 1) devuelve "obody".
Preguntas frecuentes
¿Cómo obtengo los últimos caracteres de una cadena en PHP?
Usa un desplazamiento negativo: substr($s, -3) devuelve los 3 últimos caracteres. Para texto que puede contener japonés u otros caracteres multibyte, usa mb_substr($s, -3).
¿Cuál es la diferencia entre substr y mb_substr?
substr() cuenta bytes y mb_substr() cuenta caracteres. En UTF-8 los kana y los kanji comunes ocupan 3 bytes cada uno, así que substr('日本語', 0, 2) parte un carácter por la mitad, mientras que mb_substr('日本語', 0, 2) devuelve "日本".
¿Qué devuelve substr si el inicio está más allá del final de la cadena?
Una cadena vacía. Desde PHP 8.0, substr('abc', 5) devuelve ""; PHP 7 devolvía false.
¿Cómo elimino el último carácter de una cadena en PHP?
substr($s, 0, -1) devuelve todo menos el último byte. Usa mb_substr($s, 0, -1) para texto multibyte, o rtrim($s, ',') si solo quieres quitar un carácter final concreto.
¿Cómo cuento cuántas veces aparece una subcadena en PHP?
substr_count($haystack, $needle): substr_count('banana', 'an') devuelve 2. Distingue mayúsculas y minúsculas y no cuenta coincidencias solapadas.