Saltar al contenido
cadenas.php · devschool

Cadenas de texto en PHP

Lección 6 de 26 · 13 min de lectura · Actualizado el

En esta lección
  1. Comillas simples y comillas dobles
  2. Meter variables dentro del texto
  3. Textos largos: heredoc y nowdoc
  4. Longitud de una cadena: strlen y mb_strlen
  5. Mayúsculas y minúsculas
  6. Quitar espacios: trim
  7. Buscar dentro de una cadena
  8. Extraer un trozo: substr
  9. Reemplazar: str_replace
  10. Dividir y unir: explode e implode
  11. Rellenar y repetir
  12. Dar formato: sprintf, printf y number_format
  13. Comparar cadenas
  14. Cadenas y HTML
  15. Errores frecuentes
  16. Resumen

Casi todo lo que maneja una web es texto: nombres de usuario, títulos de productos, direcciones de correo, el propio HTML que genera PHP. Una cadena (string) es una secuencia de caracteres, y PHP trae más de cien funciones para trabajar con ellas. En esta lección aprenderás las diferencias entre comillas simples y dobles, cómo meter variables dentro de un texto, cómo medir, buscar, recortar, reemplazar, dividir y dar formato a cadenas, y por qué las tildes y la ñ necesitan funciones especiales.

Comillas simples y comillas dobles

Una cadena se escribe entre comillas simples '...' o dobles "...". La diferencia es qué hace PHP con lo que hay dentro:

  • Con comillas dobles, PHP sustituye las variables por su valor y entiende las secuencias de escape como \n (salto de línea).
  • Con comillas simples, el texto se queda literalmente como lo escribes.
$ruta = "Faro de Cabo Mayor";
$km = 7;

echo "Ruta: $ruta ($km km)\n";
echo 'Ruta: $ruta ($km km)\n';
echo "\n";
// Ruta: Faro de Cabo Mayor (7 km)
// Ruta: $ruta ($km km)\n

La segunda línea muestra $ruta y \n tal cual, porque las comillas simples no interpretan nada.

¿Cuál usar? Una regla práctica: comillas simples para texto fijo ('Guardar', claves de arrays como $_POST['email']) y dobles cuando quieras meter variables o saltos de línea. La diferencia de velocidad entre ambas es inapreciable; elige por claridad.

Secuencias de escape

Dentro de comillas dobles, la barra invertida \ da un significado especial al carácter que la sigue:

SecuenciaSignificado
\nSalto de línea
\tTabulador
\"Comilla doble literal
\$Signo de dólar literal (no es una variable)
\\Barra invertida literal
echo "Precio:\t12 €\n";
echo "Escribe \"salir\" para terminar\n";
echo "La variable se llama \$total\n";
// Precio:	12 €
// Escribe "salir" para terminar
// La variable se llama $total

En comillas simples solo existen dos escapes: \' para una comilla simple y \\ para la barra.

echo 'L\'Hospitalet', "\n";
// L'Hospitalet

Nota: el \n produce un salto de línea en el código fuente de la página o en la terminal, pero el navegador lo muestra como un espacio. Para un salto visible en HTML necesitas <br> o un párrafo nuevo.

Meter variables dentro del texto

Que PHP sustituya variables dentro de las comillas dobles se llama interpolación. Funciona directamente con variables simples, pero con arrays u objetos conviene rodear la expresión con llaves { }:

$socio = ['nombre' => 'Lucía', 'cuota' => 35];
$bloques = 12;

echo "Hola, {$socio['nombre']}. Tu cuota es de {$socio['cuota']} €.\n";
echo "Has encadenado {$bloques}º bloque\n";
// Hola, Lucía. Tu cuota es de 35 €.
// Has encadenado 12º bloque

Las llaves sirven también para separar la variable del texto que va pegado: sin ellas, "$bloquesº" buscaría una variable llamada $bloquesº, que no existe.

La alternativa a la interpolación es la concatenación con el punto, que viste en Operadores:

$producto = "Pies de gato";
$talla = 41;
echo "Producto: " . $producto . " (talla " . $talla . ")\n";
// Producto: Pies de gato (talla 41)

Las dos formas son correctas. La interpolación suele leerse mejor en textos con muchas variables; la concatenación es más clara cuando mezclas llamadas a funciones, porque dentro de las comillas no se pueden llamar funciones.

Textos largos: heredoc y nowdoc

Para un texto de varias líneas (un correo, un trozo de HTML), las comillas se vuelven incómodas. PHP ofrece la sintaxis heredoc: empieza con <<< y un identificador que tú eliges, y termina con ese mismo identificador en su propia línea.

$nombre = "Andrés";
$fecha = "sábado 14";

$correo = <<<TXT
    Hola, $nombre:

    Tu plaza para el curso de iniciación del {$fecha} está confirmada.
    Trae ropa cómoda y "muchas ganas".
    TXT;

echo $correo, "\n";
// Hola, Andrés:
//
// Tu plaza para el curso de iniciación del sábado 14 está confirmada.
// Trae ropa cómoda y "muchas ganas".

Un heredoc se comporta como las comillas dobles (interpola variables) pero puedes escribir comillas dentro sin escaparlas. Desde PHP 7.3, la sangría del identificador de cierre se quita de todas las líneas, así que puedes indentar el bloque con el resto del código.

Si pones el identificador entre comillas simples (<<<'TXT') obtienes un nowdoc, que se comporta como las comillas simples: no interpreta nada. Es útil para mostrar código de ejemplo.

Longitud de una cadena: strlen y mb_strlen

strlen() devuelve la longitud… pero en bytes, no en caracteres. Con texto en inglés da igual, porque cada letra ocupa un byte. Pero en UTF-8, la codificación que usan todas las webs, la ñ y las letras con tilde ocupan dos bytes:

$barrio = "Peñacastillo";
echo strlen($barrio), "\n";
echo mb_strlen($barrio), "\n";
// 13
// 12

Las funciones que empiezan por mb_ (de multibyte) cuentan caracteres reales. En español, siempre que el resultado dependa de cuántas letras hay (validar que un nombre tiene como máximo 30 caracteres, cortar un resumen…), usa la versión mb_.

Función de bytesVersión segura para UTF-8
strlen()mb_strlen()
substr()mb_substr()
strtoupper()mb_strtoupper()
strtolower()mb_strtolower()
ucfirst()mb_ucfirst() (PHP 8.4)
str_pad()mb_str_pad() (PHP 8.3)

Mayúsculas y minúsculas

$via = "vía ferrata de la peña";

echo strtoupper($via), "\n";
echo mb_strtoupper($via), "\n";
echo ucfirst("bloque azul"), "\n";
echo ucwords("bloque azul"), "\n";
// VíA FERRATA DE LA PEñA
// VÍA FERRATA DE LA PEÑA
// Bloque azul
// Bloque Azul

strtoupper() solo convierte las letras sin tilde; la í y la ñ se quedan en minúscula. mb_strtoupper() lo hace bien. ucfirst() pone en mayúscula la primera letra y ucwords() la primera de cada palabra.

Un uso muy habitual es comparar sin distinguir mayúsculas: pasa los dos textos a minúsculas antes de comparar.

$respuesta = "SANTANDER";
var_dump(mb_strtolower($respuesta) === "santander");
// bool(true)

Quitar espacios: trim

trim() elimina los espacios, tabuladores y saltos de línea del principio y del final. ltrim() solo los de la izquierda y rtrim() solo los de la derecha. Es lo primero que se hace con cualquier dato que escribe un usuario, como verás en Validar y sanear.

$email = "   ana@correo.es  \n";
var_dump(trim($email));
var_dump(rtrim("1.250,00 €", " €"));
// string(13) "ana@correo.es"
// string(8) "1.250,00"

El segundo parámetro indica qué caracteres quitar: en el ejemplo, espacios y el símbolo del euro.

Buscar dentro de una cadena

PHP 8 añadió tres funciones muy legibles que devuelven true o false:

$archivo = "foto-escalada-2026.jpg";

var_dump(str_contains($archivo, "escalada"));
var_dump(str_starts_with($archivo, "foto-"));
var_dump(str_ends_with($archivo, ".png"));
// bool(true)
// bool(true)
// bool(false)

Distinguen mayúsculas y minúsculas. Si necesitas ignorarlas, convierte antes a minúsculas.

strpos: en qué posición está

Cuando necesitas saber dónde aparece un texto, usa strpos(). Devuelve la posición (empezando a contar en 0) o false si no lo encuentra. stripos() hace lo mismo sin distinguir mayúsculas.

$frase = "Cuerda de 60 metros";

var_dump(strpos($frase, "60"));
var_dump(strpos($frase, "Cuerda"));
var_dump(strpos($frase, "70"));
// int(10)
// int(0)
// bool(false)

Aquí está la trampa clásica: si el texto está al principio, strpos() devuelve 0, y 0 es un valor falso. Por eso siempre se compara con === false:

$frase = "Cuerda de 60 metros";

if (strpos($frase, "Cuerda") === false) {
    echo "No aparece\n";
} else {
    echo "Aparece\n";
}
// Aparece

Consejo: si solo quieres saber si un texto contiene otro, usa str_contains(). Verás strpos(...) !== false en mucho código anterior a PHP 8 que hace exactamente eso.

substr_count() cuenta cuántas veces aparece un texto:

echo substr_count("pa-ta-ta-ta", "ta"), "\n";
// 3

Extraer un trozo: substr

substr($texto, $inicio, $longitud) devuelve una parte de la cadena. Si $inicio es negativo, cuenta desde el final; si omites la longitud, llega hasta el final.

$codigo = "RES-2026-0457";

echo substr($codigo, 0, 3), "\n";
echo substr($codigo, 4, 4), "\n";
echo substr($codigo, -4), "\n";
// RES
// 2026
// 0457

También puedes leer un carácter suelto con corchetes, como si la cadena fuera un array: $codigo[0] es "R" y $codigo[-1] es "7". Pero, igual que substr(), trabaja con bytes: con letras acentuadas usa mb_substr().

$titulo = "Escalada en Picos de Europa: guía para empezar";
$resumen = mb_substr($titulo, 0, 20) . "…";
echo $resumen, "\n";
// Escalada en Picos de…

Reemplazar: str_replace

str_replace($buscar, $reemplazo, $texto) cambia todas las apariciones de un texto por otro:

$aviso = "El rocódromo abre de 10:00 a 22:00";
echo str_replace("22:00", "23:00", $aviso), "\n";
// El rocódromo abre de 10:00 a 23:00

Puedes pasar arrays para hacer varios cambios a la vez. Es muy práctico para generar slugs (la parte de la URL de un artículo):

$titulo = "Nudos básicos para escalar";
$slug = str_replace(
    [" ", "á", "é", "í", "ó", "ú", "ñ"],
    ["-", "a", "e", "i", "o", "u", "n"],
    mb_strtolower($titulo)
);
echo $slug, "\n";
// nudos-basicos-para-escalar

str_ireplace() hace lo mismo sin distinguir mayúsculas.

Dividir y unir: explode e implode

explode($separador, $texto) parte una cadena en un array usando un separador. implode($separador, $array) hace lo contrario: une los elementos de un array en una cadena.

$etiquetas = "boulder,vía,iniciación";
$lista = explode(",", $etiquetas);
print_r($lista);

echo implode(" | ", $lista), "\n";
// Array
// (
//     [0] => boulder
//     [1] => vía
//     [2] => iniciación
// )
// boulder | vía | iniciación

print_r() muestra el contenido de un array de forma legible; lo usarás mucho en Arrays. Estas dos funciones aparecen constantemente: leer líneas de un CSV, separar nombre y apellidos, mostrar una lista separada por comas…

[$nombre, $dominio] = explode("@", "marta@ejemplo.es");
echo "Usuario: $nombre, dominio: $dominio\n";
// Usuario: marta, dominio: ejemplo.es

Rellenar y repetir

str_pad() rellena una cadena hasta una longitud. Es perfecto para números con ceros a la izquierda o columnas alineadas en la terminal. str_repeat() repite un texto varias veces.

echo str_pad("7", 4, "0", STR_PAD_LEFT), "\n";
echo str_pad("Bloque", 10, "."), "V3\n";
echo str_repeat("★", 4), str_repeat("☆", 1), "\n";
// 0007
// Bloque....V3
// ★★★★☆

Dar formato: sprintf, printf y number_format

sprintf() construye una cadena a partir de una plantilla con huecos que empiezan por %. printf() hace lo mismo pero la imprime directamente.

HuecoQué inserta
%sUna cadena
%dUn entero
%.2fUn decimal con 2 cifras
%05dUn entero de 5 cifras rellenado con ceros
%-10sUna cadena alineada a la izquierda en 10 posiciones
%%Un signo % literal
$producto = "Magnesio";
$precio = 6.5;
$descuento = 15;

$linea = sprintf("%s: %.2f € (-%d%%)", $producto, $precio, $descuento);
echo $linea, "\n";

printf("Pedido nº %05d\n", 384);
// Magnesio: 6.50 € (-15%)
// Pedido nº 00384

sprintf() usa el punto como separador decimal. Para mostrar cantidades al estilo español (coma decimal y punto en los miles), usa number_format($numero, $decimales, $sepDecimal, $sepMiles):

$facturacion = 15420.5;
echo number_format($facturacion, 2, ",", "."), " €\n";
echo number_format(1234567), "\n";
// 15.420,50 €
// 1,234,567

Sin los dos últimos parámetros, number_format() usa el formato inglés.

Cuidado: number_format() devuelve una cadena. Úsala solo al mostrar el dato, nunca antes de hacer cálculos: "15.420,50" * 2 no da lo que esperas.

Comparar cadenas

Para saber si dos cadenas son iguales, usa ===. Para ordenarlas necesitas saber cuál va antes, y para eso existen:

  • strcmp($a, $b): devuelve un número negativo si $a va antes, 0 si son iguales y positivo si va después. Distingue mayúsculas.
  • strcasecmp($a, $b): igual, pero sin distinguir mayúsculas.
  • strnatcmp($a, $b): orden natural, el que esperaría una persona con números dentro del texto.
var_dump(strcmp("foto10.jpg", "foto9.jpg") < 0);
var_dump(strnatcmp("foto10.jpg", "foto9.jpg") < 0);
var_dump(strcasecmp("BOULDER", "boulder"));
// bool(true)
// bool(false)
// int(0)

Con strcmp(), "foto10" va antes que "foto9" porque compara carácter a carácter y "1" es menor que "9". Con strnatcmp(), el 9 va antes que el 10, como es lógico. Estas funciones son las que usarás para ordenar listas en Funciones de arrays.

Cadenas y HTML

Dos funciones relacionan las cadenas con el HTML que genera PHP:

  • nl2br() convierte los saltos de línea en <br>, para mostrar un texto que el usuario escribió en un <textarea> respetando sus líneas.
  • htmlspecialchars() convierte <, >, & y las comillas en entidades HTML. Es obligatoria antes de imprimir cualquier texto que venga del usuario, para evitar ataques XSS. Lo tienes explicado en Validar y sanear.
$comentario = "Gran vía\n<b>¡Repetiré!</b>";
echo nl2br(htmlspecialchars($comentario)), "\n";
// Gran vía<br />
// &lt;b&gt;¡Repetiré!&lt;/b&gt;

Fíjate en el orden: primero se escapa y después se añaden los <br>. Al revés, htmlspecialchars() también escaparía los <br>.

Errores frecuentes

  • Esperar que las comillas simples interpreten variables: 'Hola $nombre' muestra $nombre tal cual. Usa comillas dobles o concatena.
  • Comprobar strpos() con if (strpos(...)): si el texto está en la posición 0, la condición es falsa. Compara con === false o usa str_contains().
  • Contar letras con strlen(): con tildes y eñes da más de lo esperado. Usa mb_strlen() y el resto de funciones mb_.
  • Concatenar con +: en PHP se une con .; + intenta sumar y da error.
  • Hacer cálculos con el resultado de number_format(): es texto con formato, solo para mostrar.
  • Imprimir datos del usuario sin htmlspecialchars(): abre la puerta a inyectar HTML y JavaScript en tu página.
  • Llamar a funciones dentro de las comillas: "Total: strtoupper($x)" no ejecuta nada. Concatena: "Total: " . strtoupper($x).

Resumen

TareaFunción o sintaxis
Texto literal / con variables'...' / "...", {$array['clave']}
Texto largoheredoc <<<TXT ... TXT;
Longitudmb_strlen() (caracteres), strlen() (bytes)
Mayúsculasmb_strtoupper(), mb_strtolower(), ucfirst(), ucwords()
Quitar espaciostrim(), ltrim(), rtrim()
Buscarstr_contains(), str_starts_with(), str_ends_with(), strpos() === false
Extraersubstr(), mb_substr(), $texto[0]
Reemplazarstr_replace(), str_ireplace()
Dividir / unirexplode() / implode()
Rellenar / repetirstr_pad(), str_repeat()
Formatearsprintf(), printf(), number_format()
Comparar / ordenar===, strcmp(), strcasecmp(), strnatcmp()
HTMLhtmlspecialchars(), nl2br()

En la siguiente lección harás que tus programas tomen decisiones: condicionales.

Pon a prueba lo que has aprendido

[PHP] ¿Qué muestra este código?
echo strlen("Año"), mb_strlen("Año");

[PHP] El texto es "Cuerda de 60 m". ¿Qué hace este código?
$frase = "Cuerda de 60 m";
if (strpos($frase, "Cuerda")) {
    echo "si";
} else {
    echo "no";
}

[PHP] ¿Qué muestra este código?
echo substr("RES-2026-0457", -4), str_pad("7", 4, "0", STR_PAD_LEFT);

[PHP] Con $nombre = "Ana", ¿qué muestra este código?
echo 'Hola $nombre\n';

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.