Módulo 05: Arrays
Objetivos del módulo
- Comprender qué es un array en PHP y por qué es la estructura de datos más usada
- Crear arrays indexados, asociativos y multidimensionales
- Añadir, modificar y eliminar elementos
- Recorrer arrays de distintas formas
- Dominar las funciones esenciales de arrays
- Ordenar arrays con las funciones nativas y con criterios personalizados
- Usar funciones de orden superior:
array_map(),array_filter(),array_reduce()yarray_walk() - Aprovechar las novedades de PHP 8.4 (
array_find(),array_any(),array_all()…) y PHP 8.5 (array_first(),array_last()) - Desestructurar arrays en variables
- Usar arrays como pilas y colas
1. ¿Qué es un array?
📘 Concepto: Un array es una variable que guarda varios valores organizados como pares clave → valor. Si una variable normal es una caja, un array es una cajonera: cada cajón tiene una etiqueta (la clave) y un contenido (el valor).
En PHP, los arrays son extraordinariamente versátiles: el mismo tipo array sirve como lista, diccionario, pila, cola, tabla o árbol. Por eso los encontrarás en todas partes: los datos de un formulario ($_POST), las filas de una consulta a la base de datos, la configuración de una aplicación, la respuesta de una API en JSON…
| Tipo de array | Claves | Ejemplo |
|---|---|---|
| Indexado (lista) | Números enteros automáticos: 0, 1, 2… | ['rojo', 'verde', 'azul'] |
| Asociativo (diccionario) | Cadenas que tú eliges | ['nombre' => 'Ana', 'edad' => 30] |
| Multidimensional | Arrays dentro de arrays | [['id' => 1], ['id' => 2]] |
📘 Concepto: Técnicamente, en PHP todos los arrays son mapas ordenados: conservan el orden en que se insertan los elementos y sus claves pueden ser enteros o cadenas. Un array “indexado” es simplemente uno cuyas claves son 0, 1, 2… consecutivas.
2. Crear arrays
Sintaxis [] frente a array()
<?php
declare(strict_types=1);
// Sintaxis corta (PHP 5.4+): la recomendada
$colores = ['rojo', 'verde', 'azul'];
// Sintaxis antigua: equivalente, la verás en código heredado
$colores = array('rojo', 'verde', 'azul');
// Array vacío
$carrito = [];
💡 Consejo: Usa siempre
[]. Es más corta, más legible y la que recomiendan los estándares actuales.array()solo aparece en código antiguo.
Arrays indexados
<?php
declare(strict_types=1);
$dias = ['lunes', 'martes', 'miércoles', 'jueves', 'viernes'];
echo $dias[0] . PHP_EOL; // lunes ← ¡el primer índice es 0!
echo $dias[4] . PHP_EOL; // viernes
echo count($dias) . PHP_EOL; // 5
// Índice que no existe
echo $dias[10]; // Warning: Undefined array key 10
Arrays asociativos
Las claves se definen con =>:
<?php
declare(strict_types=1);
$libro = [
'titulo' => 'Cien años de soledad',
'autor' => 'Gabriel García Márquez',
'anio' => 1967,
'disponible' => true,
];
echo $libro['titulo'] . PHP_EOL; // Cien años de soledad
echo "Publicado en {$libro['anio']}" . PHP_EOL; // Publicado en 1967
💡 Consejo: Deja una coma tras el último elemento cuando escribas un array en varias líneas (trailing comma). Al añadir un elemento nuevo, solo cambia una línea y evitas errores por olvidar la coma.
Arrays multidimensionales
Un array puede contener otros arrays. Así se representan tablas, árboles o estructuras JSON:
<?php
declare(strict_types=1);
// Tabla: lista de filas (como el resultado de una consulta SQL)
$alumnos = [
['nombre' => 'Irene', 'curso' => '1º DAW', 'notas' => [8, 7.5, 9]],
['nombre' => 'Jorge', 'curso' => '2º DAW', 'notas' => [6, 5, 7]],
];
echo $alumnos[0]['nombre'] . PHP_EOL; // Irene
echo $alumnos[1]['notas'][2] . PHP_EOL; // 7
// Matriz 3x3
$matriz = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
echo $matriz[1][2] . PHP_EOL; // 6 (fila 1, columna 2)
Crear arrays con funciones: range()
<?php
print_r(range(1, 5)); // [1, 2, 3, 4, 5]
print_r(range(0, 20, 5)); // [0, 5, 10, 15, 20]
print_r(range('a', 'e')); // ['a', 'b', 'c', 'd', 'e']
print_r(range(10, 1, 3)); // [10, 7, 4, 1] - también descendente
3. Añadir, modificar y eliminar elementos
Añadir y modificar
<?php
declare(strict_types=1);
$frutas = ['manzana', 'pera'];
$frutas[] = 'kiwi'; // Añade al final (clave 2)
$frutas[0] = 'fresa'; // Modifica el elemento 0
$persona = ['nombre' => 'Raúl'];
$persona['email'] = 'raul@ejemplo.es'; // Añade una clave nueva
$persona['nombre'] = 'Raúl Gómez'; // Modifica una clave existente
print_r($frutas); // [fresa, pera, kiwi]
print_r($persona); // [nombre => Raúl Gómez, email => raul@ejemplo.es]
Funciones para añadir y quitar por los extremos
| Función | Qué hace | Devuelve |
|---|---|---|
array_push($a, ...$valores) | Añade al final | El nuevo número de elementos |
array_pop($a) | Quita el último | El elemento quitado (o null si está vacío) |
array_unshift($a, ...$valores) | Añade al principio (reindexa) | El nuevo número de elementos |
array_shift($a) | Quita el primero (reindexa) | El elemento quitado (o null) |
<?php
declare(strict_types=1);
$cola = ['Ana', 'Luis'];
array_push($cola, 'Marta', 'Pablo'); // [Ana, Luis, Marta, Pablo]
$ultimo = array_pop($cola); // $ultimo = 'Pablo' → [Ana, Luis, Marta]
array_unshift($cola, 'Zoe'); // [Zoe, Ana, Luis, Marta]
$primero = array_shift($cola); // $primero = 'Zoe' → [Ana, Luis, Marta]
echo implode(', ', $cola); // Ana, Luis, Marta
💡 Consejo: Para añadir un elemento al final,
$array[] = $valor;es más rápido y legible quearray_push(). Reservaarray_push()para añadir varios a la vez.
Eliminar con unset()
<?php
$numeros = [10, 20, 30, 40];
unset($numeros[1]);
print_r($numeros);
// Array ( [0] => 10 [2] => 30 [3] => 40 ) ← ¡el índice 1 ha desaparecido, no se reindexa!
$numeros = array_values($numeros); // Reindexa: [0 => 10, 1 => 30, 2 => 40]
$config = ['debug' => true, 'cache' => false];
unset($config['debug']); // Elimina una clave asociativa
⚠️ Importante:
unset()deja “huecos” en los índices. Si después recorres el array con unfor ($i = 0; $i < count($a); $i++), accederás a índices que no existen. Usaforeacho reindexa conarray_values().
4. Recorrer arrays
<?php
declare(strict_types=1);
$stock = ['camisetas' => 25, 'pantalones' => 0, 'gorras' => 12];
// 1. foreach con valor (la forma más habitual)
foreach ($stock as $unidades) {
echo $unidades . ' ';
}
echo PHP_EOL; // 25 0 12
// 2. foreach con clave y valor
foreach ($stock as $producto => $unidades) {
$estado = $unidades > 0 ? "$unidades uds." : 'AGOTADO';
echo "$producto: $estado" . PHP_EOL;
}
5. Funciones esenciales
PHP tiene más de 80 funciones para arrays. Estas son las que usarás a diario:
| Función | Qué hace | Ejemplo | Resultado |
|---|---|---|---|
count($a) | Número de elementos | count([1, 2, 3]) | 3 |
in_array($v, $a, true) | ¿Contiene el valor? | in_array(2, [1, 2], true) | true |
array_search($v, $a, true) | Clave del valor (o false) | array_search('b', ['a', 'b'], true) | 1 |
array_key_exists($k, $a) | ¿Existe la clave? (aunque valga null) | array_key_exists('x', ['x' => null]) | true |
array_keys($a) | Lista de claves | array_keys(['a' => 1, 'b' => 2]) | ['a', 'b'] |
array_values($a) | Lista de valores (reindexada) | array_values(['a' => 1, 'b' => 2]) | [1, 2] |
array_merge($a, $b) | Une arrays | array_merge([1], [2, 3]) | [1, 2, 3] |
[...$a, ...$b] | Une con el operador spread | [...[1], ...[2]] | [1, 2] |
array_slice($a, $inicio, $long) | Extrae una porción (sin modificar) | array_slice([1, 2, 3, 4], 1, 2) | [2, 3] |
array_splice($a, $inicio, $long, $nuevos) | Quita/sustituye una porción (modifica) | ver ejemplo | — |
array_combine($claves, $valores) | Crea un array asociativo | array_combine(['a', 'b'], [1, 2]) | ['a' => 1, 'b' => 2] |
array_flip($a) | Intercambia claves y valores | array_flip(['a' => 1]) | [1 => 'a'] |
array_unique($a) | Elimina duplicados (conserva claves) | array_unique([1, 1, 2]) | [0 => 1, 2 => 2] |
array_column($a, $col, $indice) | Extrae una columna | ver ejemplo | — |
array_sum($a) / array_product($a) | Suma / producto | array_sum([1, 2, 3]) | 6 |
array_reverse($a) | Invierte el orden | array_reverse([1, 2, 3]) | [3, 2, 1] |
array_fill($inicio, $n, $v) | Crea un array relleno | array_fill(0, 3, 'x') | ['x', 'x', 'x'] |
array_key_first($a) / array_key_last($a) | Primera / última clave | array_key_last(['a' => 1, 'b' => 2]) | 'b' |
array_is_list($a) | ¿Claves 0, 1, 2… consecutivas? (PHP 8.1) | array_is_list([1 => 'a']) | false |
range($ini, $fin, $paso) | Crea una secuencia | range(1, 3) | [1, 2, 3] |
compact('a', 'b') | Crea un array desde variables | ver ejemplo | — |
extract($a) | Crea variables desde un array | ver ejemplo | — |
Buscar: in_array(), array_search() y array_key_exists()
<?php
declare(strict_types=1);
$roles = ['editor', 'autor', 'admin'];
var_dump(in_array('admin', $roles, true)); // bool(true)
var_dump(array_search('autor', $roles, true)); // int(1)
var_dump(array_search('lector', $roles, true)); // bool(false)
// ⚠️ Trampa: array_search puede devolver 0, que es "falso"
$posicion = array_search('editor', $roles, true); // 0
if ($posicion !== false) { // ✅ Compara con !== false
echo "Encontrado en la posición $posicion" . PHP_EOL;
}
⚠️ Importante: Pasa siempre
truecomo tercer argumento dein_array()yarray_search()para que comparen con===. Sin él comparan con==:in_array('1e1', ['10'])devuelvetrue, ein_array(0, ['a', null])también (porque0 == null).
Unir arrays: array_merge(), spread y +
<?php
declare(strict_types=1);
$basicos = ['pan', 'leche'];
$extra = ['café', 'galletas'];
print_r(array_merge($basicos, $extra)); // [pan, leche, café, galletas]
print_r([...$basicos, ...$extra]); // Igual, con el operador spread
print_r([...$basicos, 'huevos', ...$extra]); // Puedes intercalar valores
// Con claves de texto, el último valor gana
$porDefecto = ['tema' => 'claro', 'idioma' => 'es', 'avisos' => true];
$usuario = ['tema' => 'oscuro'];
print_r(array_merge($porDefecto, $usuario));
// [tema => oscuro, idioma => es, avisos => 1]
print_r([...$porDefecto, ...$usuario]); // Igual (claves de texto en spread desde PHP 8.1)
// El operador + conserva el valor del PRIMER array si la clave se repite
print_r($usuario + $porDefecto);
// [tema => oscuro, idioma => es, avisos => 1]
| Forma | Claves numéricas | Claves de texto repetidas |
|---|---|---|
array_merge($a, $b) | Se renumeran (0, 1, 2…) | Gana $b |
[...$a, ...$b] | Se renumeran | Gana $b |
$a + $b | Se conservan; si se repiten, gana $a | Gana $a |
Porciones: array_slice() y array_splice()
<?php
declare(strict_types=1);
$ranking = ['Oro', 'Plata', 'Bronce', 'Cuarto', 'Quinto'];
// array_slice NO modifica el original
$podio = array_slice($ranking, 0, 3); // [Oro, Plata, Bronce]
$ultimos = array_slice($ranking, -2); // [Cuarto, Quinto] (negativo: desde el final)
// array_splice SÍ modifica el original y devuelve lo eliminado
$letras = ['a', 'b', 'c', 'd', 'e'];
$quitadas = array_splice($letras, 1, 2, ['X', 'Y', 'Z']);
print_r($quitadas); // [b, c]
print_r($letras); // [a, X, Y, Z, d, e]
Combinar, invertir y eliminar duplicados
<?php
declare(strict_types=1);
$codigos = ['ES', 'FR', 'PT'];
$paises = ['España', 'Francia', 'Portugal'];
$mapa = array_combine($codigos, $paises);
// [ES => España, FR => Francia, PT => Portugal]
$inverso = array_flip($mapa);
// [España => ES, Francia => FR, Portugal => PT]
$etiquetas = ['php', 'web', 'php', 'mysql', 'web'];
$sinRepetir = array_values(array_unique($etiquetas));
// [php, web, mysql]
Extraer columnas: array_column()
Imprescindible con datos tabulares:
<?php
declare(strict_types=1);
$usuarios = [
['id' => 7, 'nombre' => 'Clara', 'email' => 'clara@ejemplo.es'],
['id' => 12, 'nombre' => 'Diego', 'email' => 'diego@ejemplo.es'],
['id' => 15, 'nombre' => 'Eva', 'email' => 'eva@ejemplo.es'],
];
$nombres = array_column($usuarios, 'nombre');
// [Clara, Diego, Eva]
$emailsPorId = array_column($usuarios, 'email', 'id');
// [7 => clara@ejemplo.es, 12 => diego@ejemplo.es, 15 => eva@ejemplo.es]
$usuariosPorId = array_column($usuarios, null, 'id');
// [7 => [...Clara...], 12 => [...Diego...], 15 => [...Eva...]]
echo $usuariosPorId[12]['nombre']; // Diego
compact() y extract()
<?php
declare(strict_types=1);
$titulo = 'Inicio';
$usuario = 'Marina';
// compact: de variables a array (muy usado al pasar datos a plantillas)
$datos = compact('titulo', 'usuario');
// ['titulo' => 'Inicio', 'usuario' => 'Marina']
// extract: de array a variables
extract(['color' => 'azul', 'talla' => 'M']);
echo "$color $talla"; // azul M
⚠️ Importante: Nunca uses
extract()con datos del usuario (extract($_POST)): un atacante podría crear o sobrescribir cualquier variable ($esAdmin,$precio…). Igual que las variables de variables del módulo 02,extract()oculta de dónde salen las variables. Úsalo, como mucho, en motores de plantillas muy controlados.
6. Ordenar arrays
Funciones de ordenación
| Función | Ordena por | Orden | ¿Conserva las claves? |
|---|---|---|---|
sort() | Valor | Ascendente | ❌ Reindexa |
rsort() | Valor | Descendente | ❌ Reindexa |
asort() | Valor | Ascendente | ✅ Sí |
arsort() | Valor | Descendente | ✅ Sí |
ksort() | Clave | Ascendente | ✅ Sí |
krsort() | Clave | Descendente | ✅ Sí |
usort() | Función propia (valor) | Personalizado | ❌ Reindexa |
uasort() | Función propia (valor) | Personalizado | ✅ Sí |
uksort() | Función propia (clave) | Personalizado | ✅ Sí |
natsort() | Valor, orden “natural” | Ascendente | ✅ Sí |
⚠️ Importante: Todas las funciones de ordenación modifican el array original (lo reciben por referencia) y devuelven
true. No escribas$ordenado = sort($numeros);:$ordenadovaldríatrue.
<?php
declare(strict_types=1);
$numeros = [42, 7, 19, 3, 25];
sort($numeros);
print_r($numeros); // [3, 7, 19, 25, 42]
$edades = ['Lucas' => 34, 'Ana' => 28, 'Teo' => 41];
asort($edades); // Por valor, conservando quién es quién
print_r($edades); // [Ana => 28, Lucas => 34, Teo => 41]
ksort($edades); // Por clave (nombre)
print_r($edades); // [Ana => 28, Lucas => 34, Teo => 41]
Ordenación personalizada con usort() y <=>
usort() recibe una función que compara dos elementos y devuelve un número negativo, cero o positivo. El operador <=> del módulo 03 hace exactamente eso:
<?php
declare(strict_types=1);
$productos = [
['nombre' => 'Auriculares', 'precio' => 59.0, 'valoracion' => 4.5],
['nombre' => 'Altavoz', 'precio' => 35.0, 'valoracion' => 4.8],
['nombre' => 'Micrófono', 'precio' => 89.0, 'valoracion' => 4.5],
];
// Por precio ascendente
usort($productos, fn(array $a, array $b): int => $a['precio'] <=> $b['precio']);
echo implode(', ', array_column($productos, 'nombre')) . PHP_EOL;
// Altavoz, Auriculares, Micrófono
// Por valoración descendente y, a igualdad, por precio ascendente
usort($productos, fn(array $a, array $b): int =>
[$b['valoracion'], $a['precio']] <=> [$a['valoracion'], $b['precio']]
);
echo implode(', ', array_column($productos, 'nombre')) . PHP_EOL;
// Altavoz, Auriculares, Micrófono
💡 Consejo: Comparar arrays con
<=>compara elemento a elemento, así que[$a1, $a2] <=> [$b1, $b2]es una forma elegante de ordenar por varios criterios. Fíjate en que para el criterio descendente se intercambia$apor$b.
📘 Concepto: Desde PHP 8.0, la ordenación es estable: si dos elementos son “iguales” según tu criterio, mantienen el orden que tenían. Esto permite ordenar en varias pasadas sin perder la ordenación previa.
7. Funciones de orden superior
📘 Concepto: Una función de orden superior es una función que recibe otra función como argumento. En lugar de escribir un bucle, le dices a PHP qué hacer con cada elemento y él se encarga de recorrer el array. Es el estilo de programación funcional.
Las funciones que pasamos suelen ser arrow functions (fn($x) => ...), que verás a fondo en el módulo 07.
array_map(): transformar cada elemento
Aplica una función a cada elemento y devuelve un array nuevo con los resultados:
<?php
declare(strict_types=1);
$precios = [10.0, 25.5, 8.0];
$conIva = array_map(fn(float $p): float => round($p * 1.21, 2), $precios);
print_r($conIva); // [12.1, 30.86, 9.68]
$nombres = ['ana', 'luis', 'marta'];
$capitalizados = array_map(ucfirst(...), $nombres); // First-class callable
print_r($capitalizados); // [Ana, Luis, Marta]
// Con varios arrays: recorre en paralelo
$productos = ['Café', 'Té'];
$cantidades = [2, 3];
$lineas = array_map(fn(string $p, int $c): string => "$c x $p", $productos, $cantidades);
print_r($lineas); // [2 x Café, 3 x Té]
array_filter(): quedarse con algunos elementos
Devuelve solo los elementos para los que la función devuelve true. Conserva las claves:
<?php
declare(strict_types=1);
$notas = ['Ana' => 8.5, 'Luis' => 4.0, 'Marta' => 6.75, 'Pablo' => 3.5];
$aprobados = array_filter($notas, fn(float $nota): bool => $nota >= 5);
print_r($aprobados); // [Ana => 8.5, Marta => 6.75]
// Filtrar por CLAVE
$config = ['db_host' => 'localhost', 'db_user' => 'root', 'app_name' => 'Tienda'];
$soloDb = array_filter(
$config,
fn(string $clave): bool => str_starts_with($clave, 'db_'),
ARRAY_FILTER_USE_KEY
);
print_r($soloDb); // [db_host => localhost, db_user => root]
// Filtrar por clave Y valor
$stock = ['manzanas' => 0, 'peras' => 12, 'plátanos' => 3];
$pocasUnidades = array_filter(
$stock,
fn(int $unidades, string $fruta): bool => $unidades > 0 && $unidades < 5,
ARRAY_FILTER_USE_BOTH
);
print_r($pocasUnidades); // [plátanos => 3]
// Sin función: elimina los valores "falsos" (0, '', null, false, [])
print_r(array_filter([1, 0, 'hola', '', null, 'adiós']));
// [0 => 1, 2 => hola, 5 => adiós]
⚠️ Importante: Como
array_filter()conserva las claves, el resultado de filtrar una lista puede tener huecos ([0 => ..., 2 => ...]). Si necesitas una lista limpia (por ejemplo, parajson_encode(), que de lo contrario generaría un objeto), envuelve el resultado enarray_values().
array_reduce(): reducir a un único valor
Recorre el array acumulando un resultado. Recibe la función, que a su vez recibe el acumulador y el elemento actual, y el valor inicial:
<?php
declare(strict_types=1);
$carrito = [
['producto' => 'Libro', 'precio' => 18.0, 'cantidad' => 2],
['producto' => 'Agenda', 'precio' => 9.5, 'cantidad' => 1],
];
$total = array_reduce(
$carrito,
fn(float $acumulado, array $linea): float => $acumulado + $linea['precio'] * $linea['cantidad'],
0.0
);
echo "Total: $total €" . PHP_EOL; // Total: 45.5 €
| Vuelta | $acumulado | $linea | Resultado |
|---|---|---|---|
| 1 | 0.0 | Libro (18 × 2) | 36.0 |
| 2 | 36.0 | Agenda (9.5 × 1) | 45.5 |
array_walk(): recorrer modificando en el sitio
array_walk() llama a la función con cada valor (por referencia, si quieres) y su clave. A diferencia de array_map(), modifica el array original y no devuelve uno nuevo:
<?php
declare(strict_types=1);
$precios = ['café' => 1.2, 'tostada' => 2.0];
array_walk($precios, function (float &$precio, string $producto): void {
$precio = round($precio * 1.10, 2); // Subida del 10 %
});
print_r($precios); // [café => 1.32, tostada => 2.2]
8. Novedades de PHP 8.4 y 8.5
PHP 8.4: array_find(), array_find_key(), array_any() y array_all()
Antes había que escribir un foreach con break (o abusar de array_filter()) para tareas muy comunes. PHP 8.4 añadió cuatro funciones. Todas reciben el array y una función que recibe ($valor, $clave):
| Función | Devuelve |
|---|---|
array_find($a, $fn) | El primer valor que cumple la condición, o null |
array_find_key($a, $fn) | La clave del primer elemento que la cumple, o null |
array_any($a, $fn) | true si algún elemento la cumple |
array_all($a, $fn) | true si todos la cumplen |
<?php
declare(strict_types=1);
$productos = [
'P01' => ['nombre' => 'Silla', 'precio' => 49.0, 'stock' => 10],
'P02' => ['nombre' => 'Mesa', 'precio' => 149.0, 'stock' => 0],
'P03' => ['nombre' => 'Lámpara', 'precio' => 29.0, 'stock' => 4],
];
// Primer producto agotado
$agotado = array_find($productos, fn(array $p): bool => $p['stock'] === 0);
echo $agotado['nombre'] . PHP_EOL; // Mesa
// Su código
$codigo = array_find_key($productos, fn(array $p): bool => $p['stock'] === 0);
echo $codigo . PHP_EOL; // P02
// ¿Hay algún producto de más de 100 €?
var_dump(array_any($productos, fn(array $p): bool => $p['precio'] > 100)); // bool(true)
// ¿Todos tienen stock?
var_dump(array_all($productos, fn(array $p): bool => $p['stock'] > 0)); // bool(false)
// Si nada coincide, array_find devuelve null
var_dump(array_find($productos, fn(array $p): bool => $p['precio'] > 1000)); // NULL
⚠️ Importante:
array_find()devuelvenulltanto si no encuentra nada como si el valor encontrado esnull. Si tu array puede contenernull, usaarray_find_key()y comprueba la clave con!== null.
PHP 8.5: array_first() y array_last()
Obtener el primer o el último valor de un array era sorprendentemente incómodo: reset() y end() mueven el puntero interno y no funcionan con expresiones, y $a[0] falla si las claves no empiezan en 0. PHP 8.5 lo resuelve:
<?php
declare(strict_types=1);
$clasificacion = ['Lola' => 98, 'Hugo' => 91, 'Noa' => 87];
echo array_first($clasificacion) . PHP_EOL; // 98
echo array_last($clasificacion) . PHP_EOL; // 87
// Combinadas con las de claves (PHP 7.3)
echo array_key_first($clasificacion) . PHP_EOL; // Lola
echo array_key_last($clasificacion) . PHP_EOL; // Noa
// Con un array vacío devuelven null
var_dump(array_first([])); // NULL
// Funcionan con cualquier tipo de claves
$huecos = [5 => 'cinco', 2 => 'dos', 9 => 'nueve'];
echo array_first($huecos) . PHP_EOL; // cinco (el primero en orden, no la clave menor)
| Antes de PHP 8.5 | PHP 8.5 |
|---|---|
$a[array_key_first($a)] ?? null | array_first($a) |
$a[array_key_last($a)] ?? null | array_last($a) |
reset($a) (mueve el puntero, devuelve false si está vacío) | array_first($a) |
end($a) (mueve el puntero, devuelve false si está vacío) | array_last($a) |
9. Desestructuración
📘 Concepto: Desestructurar es extraer los elementos de un array a variables individuales en una sola instrucción. Es como vaciar una caja de herramientas colocando cada herramienta en su sitio.
Con arrays indexados
<?php
declare(strict_types=1);
$coordenadas = [40.4168, -3.7038];
[$latitud, $longitud] = $coordenadas;
echo "Lat: $latitud, Lon: $longitud" . PHP_EOL; // Lat: 40.4168, Lon: -3.7038
// Saltar elementos
[, $segundo, , $cuarto] = ['a', 'b', 'c', 'd'];
echo $segundo . $cuarto . PHP_EOL; // bd
// Intercambiar variables sin variable auxiliar
$a = 1;
$b = 2;
[$a, $b] = [$b, $a];
echo "$a $b" . PHP_EOL; // 2 1
Con claves
<?php
declare(strict_types=1);
$usuario = ['id' => 42, 'nombre' => 'Olga', 'email' => 'olga@ejemplo.es', 'rol' => 'editor'];
['nombre' => $nombre, 'email' => $email] = $usuario;
echo "$nombre <$email>" . PHP_EOL; // Olga <olga@ejemplo.es>
En un foreach
<?php
declare(strict_types=1);
$empleados = [
['nombre' => 'Sara', 'puesto' => 'Diseñadora'],
['nombre' => 'Iker', 'puesto' => 'Programador'],
];
foreach ($empleados as ['nombre' => $nombre, 'puesto' => $puesto]) {
echo "$nombre - $puesto" . PHP_EOL;
}
list(): la forma antigua
Antes de PHP 7.1 se usaba list(). Funciona igual, pero la sintaxis [] es más moderna:
<?php
list($x, $y) = [10, 20]; // Antiguo
[$x, $y] = [10, 20]; // Moderno, equivalente
list('a' => $uno) = ['a' => 1]; // También admite claves
💡 Consejo: La desestructuración brilla con funciones que devuelven varios valores:
[$cociente, $resto] = dividir(17, 5);. Lo aprovecharás en el módulo 07.
10. Arrays como pila y como cola
Pila (LIFO: el último en entrar es el primero en salir)
Como una pila de platos: pones encima y quitas de encima. Se usa para “deshacer”, historiales de navegación o analizar expresiones.
<?php
declare(strict_types=1);
$historial = [];
// Apilar (push)
$historial[] = 'Escribir "Hola"';
$historial[] = 'Poner en negrita';
$historial[] = 'Cambiar color';
// Desapilar (pop): deshacer la última acción
$deshecha = array_pop($historial);
echo "Deshecho: $deshecha" . PHP_EOL; // Deshecho: Cambiar color
echo 'Última acción: ' . array_last($historial) . PHP_EOL; // Poner en negrita
Cola (FIFO: el primero en entrar es el primero en salir)
Como la cola del supermercado. Se usa para procesar tareas en orden de llegada.
<?php
declare(strict_types=1);
$colaImpresion = ['factura.pdf', 'informe.docx'];
$colaImpresion[] = 'foto.jpg'; // Llega un trabajo nuevo al final
while (count($colaImpresion) > 0) {
$trabajo = array_shift($colaImpresion); // Atiende al primero
echo "Imprimiendo $trabajo..." . PHP_EOL;
}
// Imprimiendo factura.pdf...
// Imprimiendo informe.docx...
// Imprimiendo foto.jpg...
| Estructura | Añadir | Quitar | Consultar sin quitar |
|---|---|---|---|
| Pila (LIFO) | $a[] = $x / array_push() | array_pop() | array_last() |
| Cola (FIFO) | $a[] = $x / array_push() | array_shift() | array_first() |
💡 Consejo:
array_shift()tiene que reindexar todo el array, así que con colas de miles de elementos es lento. Para esos casos PHP ofrece clases especializadas comoSplQueueySplStack.
11. Ejemplos completos
Ejemplo 1: Carrito de la compra
<?php
declare(strict_types=1);
const IVA = 0.21;
const ENVIO_GRATIS_DESDE = 50.0;
const GASTOS_ENVIO = 4.95;
$catalogo = [
'LIB-01' => ['nombre' => 'El nombre del viento', 'precio' => 22.90],
'LIB-02' => ['nombre' => 'Dune', 'precio' => 14.95],
'CUA-01' => ['nombre' => 'Cuaderno A5', 'precio' => 3.50],
];
// El carrito guarda código => cantidad
$carrito = [];
// Añadir productos (si ya está, suma la cantidad)
$anadir = [['LIB-01', 1], ['CUA-01', 3], ['LIB-02', 1], ['CUA-01', 1]];
foreach ($anadir as [$codigo, $cantidad]) {
$carrito[$codigo] = ($carrito[$codigo] ?? 0) + $cantidad;
}
// Eliminar un producto
unset($carrito['LIB-02']);
// Construir las líneas del ticket
$lineas = array_map(
fn(string $codigo, int $cantidad): array => [
'nombre' => $catalogo[$codigo]['nombre'],
'cantidad' => $cantidad,
'subtotal' => $catalogo[$codigo]['precio'] * $cantidad,
],
array_keys($carrito),
array_values($carrito)
);
$base = array_sum(array_column($lineas, 'subtotal'));
$iva = round($base * IVA, 2);
$envio = $base >= ENVIO_GRATIS_DESDE ? 0.0 : GASTOS_ENVIO;
$total = $base + $iva + $envio;
foreach ($lineas as ['nombre' => $nombre, 'cantidad' => $cantidad, 'subtotal' => $subtotal]) {
printf("%-25s x%2d %8.2f €\n", $nombre, $cantidad, $subtotal);
}
echo str_repeat('-', 42) . PHP_EOL;
printf("%-29s %8.2f €\n", 'Base imponible', $base);
printf("%-29s %8.2f €\n", 'IVA (21 %)', $iva);
printf("%-29s %8.2f €\n", 'Transporte', $envio);
printf("%-29s %8.2f €\n", 'TOTAL', $total);
Salida:
El nombre del viento x 1 22.90 €
Cuaderno A5 x 4 14.00 €
------------------------------------------
Base imponible 36.90 €
IVA (21 %) 7.75 €
Transporte 4.95 €
TOTAL 49.60 €
Ejemplo 2: Notas de alumnos
<?php
declare(strict_types=1);
$alumnos = [
['nombre' => 'Alba', 'notas' => [7.5, 8.0, 9.25]],
['nombre' => 'Bruno', 'notas' => [4.0, 5.5, 3.75]],
['nombre' => 'Carla', 'notas' => [9.0, 9.5, 10.0]],
['nombre' => 'Dani', 'notas' => [6.0, 4.5, 5.0]],
];
// 1. Calcular la media de cada alumno
$conMedia = array_map(
fn(array $a): array => [
...$a,
'media' => round(array_sum($a['notas']) / count($a['notas']), 2),
],
$alumnos
);
// 2. Ordenar por media descendente
usort($conMedia, fn(array $a, array $b): int => $b['media'] <=> $a['media']);
// 3. Mostrar el ranking
foreach ($conMedia as $posicion => ['nombre' => $nombre, 'media' => $media]) {
$estado = $media >= 5 ? 'Aprobado' : 'Suspenso';
printf("%d. %-6s %5.2f %s\n", $posicion + 1, $nombre, $media, $estado);
}
// 4. Estadísticas
$medias = array_column($conMedia, 'media');
$aprobados = array_filter($conMedia, fn(array $a): bool => $a['media'] >= 5);
echo PHP_EOL;
echo 'Media de la clase: ' . round(array_sum($medias) / count($medias), 2) . PHP_EOL;
echo 'Mejor alumno: ' . array_first($conMedia)['nombre'] . PHP_EOL;
echo 'Aprobados: ' . count($aprobados) . ' de ' . count($conMedia) . PHP_EOL;
echo '¿Alguna matrícula de honor (10)? '
. (array_any($alumnos, fn(array $a): bool => in_array(10.0, $a['notas'], true)) ? 'Sí' : 'No')
. PHP_EOL;
Salida:
1. Carla 9.50 Aprobado
2. Alba 8.25 Aprobado
3. Dani 5.17 Aprobado
4. Bruno 4.42 Suspenso
Media de la clase: 6.84
Mejor alumno: Carla
Aprobados: 3 de 4
¿Alguna matrícula de honor (10)? Sí
12. Ejercicios
Ejercicio 1: Agenda de contactos
Crea un array asociativo de 5 contactos donde la clave sea el nombre y el valor un array con telefono y email. Implementa: añadir un contacto, modificar el teléfono de uno, eliminar otro con unset(), comprobar si existe un nombre con array_key_exists() y mostrar todos ordenados alfabéticamente con ksort().
Ejercicio 2: Operaciones de conjuntos
Dados $a = [1, 2, 3, 4, 5] y $b = [4, 5, 6, 7], obtén la unión sin duplicados, la intersección y la diferencia ($a menos $b). Investiga en el manual las funciones array_intersect() y array_diff() y úsalas. Reindexa los resultados con array_values().
Ejercicio 3: Estadísticas de temperaturas
Dado un array con las temperaturas máximas de 14 días, calcula con funciones de arrays (sin bucles): la media, la máxima, la mínima, cuántos días superaron los 30 grados (array_filter + count), las temperaturas en Fahrenheit (array_map, F = C × 9/5 + 32) y si todos los días superaron los 15 grados (array_all).
Ejercicio 4: Inventario de una tienda
Con un array de productos (codigo, nombre, categoria, precio, stock):
- Obtén un array
codigo => nombreconarray_column(). - Agrupa los productos por categoría usando
array_reduce()(resultado:['Electrónica' => [...], 'Hogar' => [...]]). - Calcula el valor total del inventario (precio × stock).
- Encuentra el primer producto sin stock con
array_find(). - Ordena por categoría y, dentro de cada categoría, por precio descendente con un único
usort().
Ejercicio 5: Palabras más frecuentes
Dado un texto largo, conviértelo en minúsculas, sepáralo en palabras con explode(' ', ...), elimina las vacías, cuenta cuántas veces aparece cada palabra (prueba la función array_count_values()), ordena de mayor a menor frecuencia con arsort() y muestra las 5 más repetidas con array_slice() (con el cuarto parámetro true para conservar las claves).
Resumen
| Concepto | Sintaxis / función |
|---|---|
| Crear | $a = [1, 2];, $a = ['clave' => 'valor']; |
| Añadir al final | $a[] = $valor;, array_push($a, $v1, $v2) |
| Quitar extremos | array_pop(), array_shift(); añadir al inicio: array_unshift() |
| Eliminar | unset($a['clave']) (no reindexa) |
| Contar / buscar | count(), in_array($v, $a, true), array_search($v, $a, true) |
| Claves y valores | array_keys(), array_values(), array_key_exists() |
| Unir | array_merge(), [...$a, ...$b], $a + $b |
| Porciones | array_slice() (copia), array_splice() (modifica) |
| Transformar estructura | array_combine(), array_flip(), array_unique(), array_column() |
| Ordenar por valor | sort(), rsort(), asort(), arsort() |
| Ordenar por clave | ksort(), krsort() |
| Orden personalizado | usort($a, fn($x, $y) => $x <=> $y) |
| Transformar | array_map(fn($v) => ..., $a) |
| Filtrar | array_filter($a, $fn, ARRAY_FILTER_USE_KEY) |
| Reducir | array_reduce($a, $fn, $inicial) |
| Modificar en el sitio | array_walk($a, function (&$v, $k) { ... }) |
| PHP 8.4 | array_find(), array_find_key(), array_any(), array_all() |
| PHP 8.5 | array_first(), array_last() |
| Desestructurar | [$a, $b] = $arr;, ['k' => $v] = $arr; |
| Pila / cola | array_pop() / array_shift() |