Curso de PHP gratis · Capítulo 3 de 13 · con Nadia Cadena
Strings en PHP: comillas, concatenación, interpolación y UTF-8
Trabajar con texto es lo que más harás en PHP. Verás la diferencia entre comillas simples y dobles, cómo concatenar e interpolar, y por qué strlen("ñ") devuelve 2.
Comillas simples y dobles
Un string se escribe entre comillas, simples o dobles, pero no son iguales:
- Comillas simples
'...': el texto va tal cual. Solo entienden\'(una comilla) y\\(una barra). - Comillas dobles
"...": PHP interpreta lo de dentro: secuencias de escape como\n(salto de línea),\t(tabulador),\"o\$... y variables.
¿Por qué dos tipos? Porque a veces quieres texto literal (por ejemplo, un texto con muchos $ o barras) y a veces quieres que PHP rellene huecos. Regla práctica: usa simples cuando el texto no tiene nada que interpretar; dobles cuando sí.
<?php
$dron = "BIT-8";
echo 'Hola $dron\n';
echo "\n";
echo "Hola $dron\n";
echo "Comillas \"dobles\" y un dólar: \$5\n";
echo 'It\'s ', "tab:\t|", "\n";Hola $dron\n Hola BIT-8 Comillas "dobles" y un dólar: $5 It's tab: |
Interpolación: rellenar huecos
Dentro de comillas dobles, PHP sustituye las variables por su valor. A esto se le llama interpolación.
Si el nombre de la variable va pegado a más letras, PHP no sabe dónde acaba: "$frutas" busca una variable llamada $frutas. Para delimitarla usa llaves: "{$fruta}s".
Las llaves también permiten meter expresiones más complejas, como elementos de un array "{$precios['heno']}" o propiedades de un objeto "{$dron->nombre}" (ya las verás).
Si intentas interpolar una variable que no existe, PHP da un Warning y la sustituye por nada. Fíjate en la última línea del ejemplo.
<?php
$fruta = "manzana";
$cantidad = 3;
echo "Tengo $cantidad {$fruta}s\n";
echo "Pesan {$cantidad}kg\n";
echo "Tengo $cantidad $frutas\n";Tengo 3 manzanas Pesan 3kg Tengo 3
Concatenar con el punto
Para unir strings se usa el operador punto . (¡no el +!). Y .= añade al final de una variable.
$saludo = "Hola" . ", " . "mundo"; $saludo .= "!"; // equivale a $saludo = $saludo . "!";
¿Por qué no + como en otros lenguajes? Porque en PHP + es siempre una suma numérica: "3" + "4" da 7. Tener un operador distinto para unir evita ambigüedades: "3" . "4" da "34".
Precedencia en PHP 8: + y - se evalúan antes que el punto. Así, "Total: " . 2 + 3 da "Total: 5". (En PHP 7 era al revés, y daba un resultado muy raro.) Ante la duda, usa paréntesis.
<?php
$saludo = "Hola" . ", " . "mundo";
$saludo .= "!";
echo $saludo, "\n";
echo "3" + "4", " frente a ", "3" . "4", "\n";
echo "Total: " . 2 + 3, "\n";
echo "Total: " . (2 * 3), "\n";Hola, mundo! 7 frente a 34 Total: 5 Total: 6
¿Qué imprime echo "10" . "5" + 1; en PHP 8?
106161051- Un error
Ver respuesta
A. 106
En PHP 8 la suma va primero: "5" + 1 = 6, y luego "10" . 6 = "106".
Funciones de cadena
PHP tiene decenas de funciones para strings. Las más útiles:
strlen($s): longitud (en bytes, ¡ojo!).strtoupper($s),strtolower($s),ucfirst($s),ucwords($s).str_repeat($s, $n): repetir.str_replace($buscar, $poner, $s): sustituir.strpos($s, $aguja): posición de la primera aparición (ofalse).str_contains,str_starts_with,str_ends_with(PHP 8).trim($s): quitar espacios de los extremos.substr($s, $inicio, $largo): un trozo.str_pad($s, $largo, $relleno): rellenar hasta un ancho.
Los strings en PHP son valores: estas funciones NO modifican el original, devuelven un string nuevo. Si quieres guardar el cambio, asígnalo: $s = strtoupper($s);.
<?php
$s = " carta para Rasmus ";
echo "[", trim($s), "]\n";
echo strtoupper(trim($s)), "\n";
echo str_replace("Rasmus", "Vera", $s), "\n";
echo strpos("hola mundo", "mundo"), "\n";
var_dump(str_contains($s, "carta"));
echo substr("BIT-8 el dron", 0, 5), "\n";
echo str_pad("7", 3, "0", STR_PAD_LEFT), "\n";
echo "[", $s, "]\n";[carta para Rasmus] CARTA PARA RASMUS carta para Vera 5 bool(true) BIT-8 007 [ carta para Rasmus ]
Bytes y caracteres: el secreto de la ñ
Aquí va el secreto: para PHP un string es una secuencia de BYTES, no de letras.
El texto se guarda con una codificación, normalmente UTF-8. En UTF-8, las letras del inglés ocupan 1 byte, pero la ñ, la á o un emoji ocupan 2, 3 o 4 bytes. Por eso strlen("piña") da 5 y no 4.
Las funciones mb_ (multibyte*) sí entienden de caracteres: mb_strlen, mb_substr, mb_strtoupper...
¿Por qué PHP funciona así? Porque nació en 1995, cuando casi todo el texto era ASCII (1 byte por letra), y tratar bytes es rapidísimo. Las funciones mb_ llegaron después para los idiomas que no caben en ASCII... como el castellano. Además, strtoupper solo cambia letras ASCII: la ñ se queda igual.
Regla práctica: si tu texto puede tener tildes o eñes y te importa la longitud o cortar letras, usa mb_.
<?php
$fruta = "piña";
echo strlen($fruta), " bytes\n";
echo mb_strlen($fruta), " caracteres\n";
echo strtoupper($fruta), " / ", mb_strtoupper($fruta), "\n";
echo substr($fruta, 0, 3), "|\n";
echo mb_substr($fruta, 0, 3), "|\n";5 bytes 4 caracteres PIñA / PIÑA pi�| piñ|
¿Qué devuelve strlen("año")?
- 3
- 4
- 2
Ver respuesta
B. 4
La ñ ocupa 2 bytes en UTF-8: 1 + 2 + 1 = 4 bytes. mb_strlen("año") sí daría 3.
Cada letra tiene su número
Puedes leer un carácter (bueno, un byte) por su posición con corchetes. Las posiciones empiezan en 0, y los índices negativos cuentan desde el final.
$s = "Zend"; $s[0]; // "Z" $s[-1]; // "d"
Si pides una posición que no existe, PHP da un Warning (Uninitialized string offset). Las posiciones válidas van de 0 a strlen($s) - 1.
<?php
$s = "Zend";
echo $s[0], $s[1], "\n";
echo $s[-1], "\n";
echo "Longitud: ", strlen($s), ", última posición: ", strlen($s) - 1, "\n";Ze d Longitud: 4, última posición: 3
Dar formato: printf y sprintf
printf imprime un texto con huecos que se rellenan con valores; sprintf hace lo mismo pero devuelve el string en vez de imprimirlo.
%s: un string.%d: un entero.%.2f: un float con 2 decimales.%5d: ancho mínimo 5 (rellena con espacios a la izquierda).%-8s: ancho 8 alineado a la izquierda.%05d: rellena con ceros.%%: un símbolo%literal.
number_format($n, $decimales, ',', '.') formatea números al estilo español: 1.234,50.
<?php
printf("%s tiene %d sacos\n", "Vera", 12);
printf("Precio: %.2f monedas\n", 3.14159);
printf("[%5d] [%-8s] [%05d]\n", 42, "heno", 7);
$etiqueta = sprintf("Lote-%03d", 5);
echo $etiqueta, "\n";
echo number_format(1234.5, 2, ',', '.'), "\n";
printf("Batería al %d%%\n", 80);Vera tiene 12 sacos Precio: 3.14 monedas [ 42] [heno ] [00007] Lote-005 1.234,50 Batería al 80%
Textos largos: heredoc
Para textos de varias líneas existe la sintaxis heredoc: empieza con <<< y un identificador, y termina con el mismo identificador en su propia línea. Se comporta como las comillas dobles (interpola variables) y no necesitas escapar comillas.
Si usas <<<'EOT' (con comillas simples) se llama nowdoc y no interpola nada, como las comillas simples.
Desde PHP 7.3, el cierre puede estar indentado, y esa indentación se quita de todas las líneas. Muy cómodo.
<?php
$para = "Rasmus";
$sacos = 12;
$carta = <<<CARTA
Querido $para:
BIT-8 ha cosechado $sacos sacos.
Un saludo, "Nadia Cadena".
CARTA;
echo $carta, "\n";Querido Rasmus: BIT-8 ha cosechado 12 sacos. Un saludo, "Nadia Cadena".
Ejercicios de Strings en PHP resueltos
Intenta resolverlos antes de mirar la solución. En el juego puedes ejecutarlos y comprobarlos automáticamente.
Encargo 1. Un mensaje por destinatario
Nadia Cadena manda la misma carta a muchos vecinos. Solo cambian el nombre y los sacos. Las variables $destinatario y $sacos ya existen (las rellena el Correo).
Imprime la carta usando las variables:
Querida Vera: BIT-8 ha cosechado 12 sacos.
Tu programa se probará con distintos vecinos, así que no escribas el nombre ni el número a mano.
Pistas
- Dentro de comillas dobles puedes escribir
$destinatariodirectamente. echo "Querida $destinatario: BIT-8 ha cosechado $sacos sacos.";
Ver solución
<?php
echo "Querida $destinatario: BIT-8 ha cosechado $sacos sacos.";
Encargo 2. Etiquetas del almacén
El granero necesita etiquetas bien alineadas. Los nombres y cantidades están en $n1, $c1, $n2, $c2 y $n3, $c3.
Imprime una etiqueta por línea: el nombre relleno con puntos hasta 10 caracteres y la cantidad alineada a la derecha en 5 caracteres:
Heno...... 40 Zanahoria. 7 Madera.... 125
Pistas
str_pad($n1, 10, ".")rellena por la derecha con puntos.- Para la cantidad:
str_pad($c1, 5, " ", STR_PAD_LEFT). - Con printf también se puede:
printf("%'.-10s%5d\n", $n1, $c1);(el'.indica que se rellena con puntos).
Ver solución
<?php
printf("%'.-10s%5d\n", $n1, $c1);
printf("%'.-10s%5d\n", $n2, $c2);
printf("%'.-10s%5d\n", $n3, $c3);
Predicción 3. El paquete misterioso
Un paquete con una piña dentro. Nadia Cadena te reta a adivinar qué sale por pantalla.
Elige la salida exacta.
<?php
$fruta = "piña";
echo strlen($fruta), " ", mb_strlen($fruta), "\n";
echo 'Sin $fruta', "\n";
echo "Con {$fruta}s";5 4 Sin $fruta Con piñas4 4 Sin piña Con piñas5 4 Sin piña Con piñas4 5 Sin $fruta Con $frutas
Ver solución
5 4 Sin $fruta Con piñas
¡Eso es! La ñ ocupa 2 bytes y las comillas simples no interpolan.
Caza de bugs 4. La transmisión corrupta
El telegrafista es nuevo y viene de otro lenguaje de programación. Su telegrama da un error rarísimo.
Arregla el programa para que imprima exactamente:
De: Cadena Para: Rasmus Llega mañana
Código de partida:
<?php
$de = "Cadena";
$para = "Rasmus";
$mensaje = "De: " + $de + " Para: " + $para;
echo $mensaje, "\n";
echo 'Llega mañana\n';
Pistas
- Lee el error:
Unsupported operand types: string + string. En PHP,+solo suma números. - Para unir strings se usa el punto
.. - Y en comillas simples
\nno es un salto de línea.
Ver solución
<?php
$de = "Cadena";
$para = "Rasmus";
$mensaje = "De: " . $de . " Para: " . $para;
echo $mensaje, "\n";
echo "Llega mañana\n";
Misión del dron 5. BIT-8 aprende a hablar
BIT-8 tiene un altavoz: decir($texto) le hace mostrar un bocadillo. Nadia Cadena quiere que informe de su trabajo.
Cosecha la hierba de debajo y la de la casilla del NORTE. Después haz que BIT-8 diga exactamente Tengo 2 de heno, construyendo el texto con el valor de inventario(HENO) (sin escribir el 2 a mano).
Esta misión mueve al dron BIT-8 por un campo de cultivo: juégala en PHPlay para ver tu código animado.
Pistas
- Guarda el inventario en una variable:
$heno = inventario(HENO); decir("Tengo $heno de heno");
Ver solución
<?php
cosechar();
mover(NORTE);
cosechar();
$heno = inventario(HENO);
decir("Tengo $heno de heno");
Chuleta: lo esencial
- Comillas simples: texto literal. Dobles: interpretan
\n,\t,\$y variables. - Interpolación:
"Hola $nombre","{$fruta}s","{$arr['k']}". - Concatenar:
$a . $b; añadir:$s .= "más";. En PHP 8,+y-van antes que el punto. - Funciones:
strlen,strtoupper,ucfirst,str_repeat,str_replace,strpos,str_contains,trim,substr,str_pad. Devuelven un string nuevo. - Un string son bytes:
strlen("ñ")= 2. Usamb_strlen,mb_substr,mb_strtouppercon tildes/eñes. $s[0]primer carácter,$s[-1]el último.printf("%s %d %.2f %5d %-8s %05d %%", ...);sprintfdevuelve el texto;number_format($n, 2, ',', '.').- Heredoc
<<<ID ... ID;(interpola) y nowdoc<<<'ID'(no interpola).