Esta guía reúne en un solo lugar ejemplos sobre arrays: desde la creación y el recorrido básico hasta las funciones más recientes del lenguaje, incluyendo array_is_list(), el spread operator con claves string, WeakMap y las nuevas array_find/array_any/array_all de PHP 8.4.

Tabla de contenidos
- Fundamentos
- Creación de arrays
- Acceso, modificación y eliminación
- Recorrido de arrays
- Búsqueda
- Ordenamiento
- Transformación: map, filter, reduce, walk
- Combinar y fusionar
- Extraer y dividir
- Claves y valores
- Matemáticas y agregación
- Comparación: diff, intersect, unique
- Desestructuración
- Operador spread (
...) - Arrays multidimensionales
- Novedades PHP 8.x en arrays
- JSON y serialización
- Casting y conversión entre arrays y objetos
- compact() y extract()
- Funciones variádicas
- Invertir el orden: array_reverse()
- Copia por valor: arrays en memoria
- Agrupar y pivotear datos
- Rendimiento y buenas prácticas
- Errores comunes
- Cheat sheet final
- Descarga los ejemplos
- Conclusión
1. Fundamentos
Un array de PHP es en realidad un mapa ordenado: una estructura que asocia claves (int o string) con valores, y que conserva el orden de inserción. Esto explica por qué el mismo tipo sirve como lista, pila, cola, tabla hash, árbol y hasta matriz.
$lista = [1, 2, 3]; // array indexado $asociativo = ['nombre' => 'Ana', 'edad' => 30]; // array asociativo $mixto = [0 => 'a', 'clave' => 'b', 5 => 'c']; // claves mixtas
Internamente PHP implementa los arrays como hash tables ordenadas (HashTable), lo que da acceso en O(1) tanto por clave numérica como por clave string, conservando el orden de inserción salvo que se ordenen explícitamente.
2. Creación de arrays
PHP ofrece varias formas de crear un array: la sintaxis moderna con corchetes, funciones que generan secuencias automáticas como range(), arrays rellenos con un valor por defecto mediante array_fill(), o la combinación de un array de claves con otro de valores. Elegir la forma adecuada según el caso ahorra líneas y deja más clara la intención del código.
// Sintaxis moderna (recomendada desde PHP 5.4)
$colores = ['rojo', 'verde', 'azul'];
// Sintaxis clásica (sigue funcionando, evitar en código nuevo)
$colores = array('rojo', 'verde', 'azul');
// Asociativo
$persona = [
'nombre' => 'Carlos',
'edad' => 28,
];
// Array vacío
$vacio = [];
// Rellenar con range()
$numeros = range(1, 10); // [1,2,...,10]
$pares = range(0, 20, 2); // [0,2,4,...,20]
$letras = range('a', 'e'); // ['a','b','c','d','e']
// Rellenar con un valor fijo
$ceros = array_fill(0, 5, 0); // [0,0,0,0,0]
$mapa = array_fill_keys(['a','b'], 0); // ['a'=>0, 'b'=>0]
// Combinar un array de claves con uno de valores
$obj = array_combine(['id', 'nombre'], [1, 'Ana']); // ['id'=>1, 'nombre'=>'Ana']Todas estas formas producen el mismo tipo de dato interno; la diferencia está solo en cuánto código hay que escribir para llegar al array que necesitas, así que conviene elegir la función que exprese mejor la intención en cada caso.
3. Acceso, modificación y eliminación
Leer, sobrescribir, añadir o quitar elementos son las operaciones más frecuentes en cualquier script. PHP ofrece funciones específicas para trabajar en ambos extremos del array (array_push/array_pop al final, array_unshift/array_shift al inicio), además del acceso directo por índice o clave con corchetes.
$frutas = ['manzana', 'pera', 'uva']; // Acceso echo $frutas[0]; // manzana echo $frutas[count($frutas) - 1]; // uva (último elemento) // Modificación $frutas[1] = 'kiwi'; // Añadir al final $frutas[] = 'mango'; array_push($frutas, 'sandía', 'melón'); // acepta varios valores // Añadir al inicio array_unshift($frutas, 'fresa'); // Quitar el último elemento $ultimo = array_pop($frutas); // Quitar el primero (reindexa las claves numéricas) $primero = array_shift($frutas); // Eliminar una clave concreta (sin reindexar) unset($frutas[2]); // Comprobar existencia isset($frutas[0]); // true si existe Y no es null array_key_exists(0, $frutas); // true aunque el valor sea null empty($frutas[0]); // true si no existe o es "falsy"
isset() es más rápido, pero devuelve false para valores null aunque la clave exista. Si necesitas distinguir “no existe” de “existe pero es null”, usa array_key_exists().
4. Recorrido de arrays
Recorrer un array es la operación más común de todas, y PHP ofrece varias herramientas para hacerlo: el idiomático foreach, el for clásico (que solo tiene sentido con arrays indexados de forma secuencial) y un conjunto de funciones basadas en un puntero interno que apunta al elemento “actual” del array.
$persona = ['nombre' => 'Ana', 'edad' => 30];
// foreach: la forma idiomática
foreach ($persona as $valor) { /* ... */ }
foreach ($persona as $clave => $valor) { /* ... */ }
// Por referencia (modifica el array original)
foreach ($persona as $clave => &$valor) {
$valor = strtoupper((string) $valor);
}
unset($valor); // IMPORTANTE: romper la referencia tras el foreach
// for clásico (solo tiene sentido con arrays indexados 0..n-1)
$lista = [10, 20, 30];
for ($i = 0; $i < count($lista); $i++) {
echo $lista[$i];
}
// Puntero interno del array
$arr = ['a', 'b', 'c'];
echo current($arr); // 'a'
echo next($arr); // 'b'
echo next($arr); // 'c'
echo prev($arr); // 'b'
echo end($arr); // 'c'
echo reset($arr); // 'a' (vuelve al inicio)
echo key($arr); // clave actual del puntero
each()existía para recorrer usando el puntero interno, pero está eliminada desde PHP 8.0. Usaforeacho las funcionescurrent()/next()/key().
5. Búsqueda
Antes de modificar o procesar datos casi siempre hace falta comprobar si un valor o una clave existen dentro del array. PHP separa claramente las funciones que buscan por valor de las que buscan por clave, y conviene prestar atención al tipo de comparación —débil o estricta— que usa cada una para evitar coincidencias falsas.
$frutas = ['manzana', 'pera', 'uva'];
in_array('pera', $frutas); // true
in_array('10', [10, 20], true); // false con comparación estricta
array_search('uva', $frutas); // 2 (índice) o false si no está
array_key_exists('uva', $frutas); // busca por CLAVE, no por valor
$persona = ['nombre' => 'Ana', 'edad' => 30];
array_key_first($persona); // 'nombre' (PHP 7.3+)
array_key_last($persona); // 'edad' (PHP 7.3+)array_search() y in_array() usan comparación débil (==) por defecto; pásales true como tercer argumento para forzar comparación estricta (===) y evitar sorpresas como 0 == 'texto'.
6. Ordenamiento
PHP dedica una familia completa de funciones al ordenamiento, y elegir la correcta depende de dos preguntas: ¿se ordena por clave o por valor?, y ¿es necesario conservar la relación clave-valor original o basta con reindexar? La siguiente tabla resume las combinaciones más comunes.
| Función | Ordena por | Conserva claves | Dirección |
|---|---|---|---|
sort() | valor | No (reindexa) | Ascendente |
rsort() | valor | No (reindexa) | Descendente |
asort() | valor | Sí | Ascendente |
arsort() | valor | Sí | Descendente |
ksort() | clave | Sí | Ascendente |
krsort() | clave | Sí | Descendente |
usort() | valor, callback | No (reindexa) | Custom |
uasort() | valor, callback | Sí | Custom |
uksort() | clave, callback | Sí | Custom |
natsort() | valor, orden natural | Sí | Ascendente |
natcasesort() | valor, natural sin mayúsculas | Sí | Ascendente |
$edades = ['Ana' => 30, 'Luis' => 25, 'Eva' => 40];
asort($edades); // ['Luis'=>25, 'Ana'=>30, 'Eva'=>40] — conserva claves
ksort($edades); // ordena por nombre (clave)
$numeros = [5, 3, 8, 1];
sort($numeros); // [1, 3, 5, 8]
// Ordenamiento personalizado
$personas = [
['nombre' => 'Ana', 'edad' => 30],
['nombre' => 'Luis', 'edad' => 25],
];
usort($personas, fn($a, $b) => $a['edad'] <=> $b['edad']);
// PHP 8: usort acepta directamente first-class callable syntax
usort($personas, strcmp(...)); // ejemplo ilustrativo del "first-class callable syntax" (8.1+)
shuffle($numeros); // desordena aleatoriamente (reindexa)El operador spaceship <=> (PHP 7+) es el estándar para callbacks de ordenamiento: devuelve -1, 0 o 1 según corresponda, evitando restas manuales propensas a overflow.
7. Transformación: map, filter, reduce, walk
Estas cuatro funciones son el corazón de la programación funcional en PHP: permiten transformar, filtrar, agregar o mutar un array sin escribir bucles manuales, favoreciendo un código más declarativo, más corto y más fácil de testear.
$numeros = [1, 2, 3, 4, 5];
// array_map: transforma cada elemento -> nuevo array del mismo tamaño
$cuadrados = array_map(fn($n) => $n ** 2, $numeros);
// array_map con varios arrays a la vez
$suma = array_map(fn($a, $b) => $a + $b, [1, 2, 3], [10, 20, 30]); // [11,22,33]
// array_map(null, ...) hace zip de varios arrays
$zip = array_map(null, ['a', 'b'], [1, 2]); // [['a',1], ['b',2]]
// array_filter: conserva solo los que cumplen la condición
$pares = array_filter($numeros, fn($n) => $n % 2 === 0);
// Ojo: array_filter NO reindexa -> usa array_values() si lo necesitas
$pares = array_values($pares);
// array_filter sin callback elimina los valores "falsy" (0, '', null, false, [])
$limpio = array_filter([0, 1, '', 'a', null, false, 'b']);
// array_filter con ARRAY_FILTER_USE_KEY o ARRAY_FILTER_USE_BOTH
array_filter($persona, fn($k) => $k !== 'password', ARRAY_FILTER_USE_KEY);
array_filter($persona, fn($v, $k) => $k !== 'id' && $v !== null, ARRAY_FILTER_USE_BOTH);
// array_reduce: colapsa el array a un único valor
$total = array_reduce($numeros, fn($acc, $n) => $acc + $n, 0); // 15
// array_walk: modifica el array in place (recibe el valor POR REFERENCIA)
array_walk($numeros, function (&$valor, $clave) {
$valor = $valor * 10;
});
// array_walk_recursive: igual pero entra en sub-arrays
array_walk_recursive($matriz, function (&$valor) {
$valor = strtoupper($valor);
});Regla mental: array_map transforma (1 a 1), array_filter selecciona (subconjunto), array_reduce agrega (a un solo valor), array_walk muta in place.
8. Combinar y fusionar
Cuando se trabaja con configuraciones, valores por defecto o datos provenientes de varias fuentes, es habitual necesitar unir dos o más arrays en uno solo. PHP ofrece varias formas de hacerlo, y cada una sigue reglas distintas sobre qué ocurre cuando dos claves coinciden.
$a = ['color' => 'rojo', 0 => 'x']; $b = ['color' => 'azul', 0 => 'y']; // array_merge: las claves string se sobrescriben, las numéricas se reindexan array_merge($a, $b); // ['color'=>'azul', 0=>'x', 1=>'y'] // Operador + : conserva las claves del PRIMER array, ignora duplicados del segundo $a + $b; // ['color'=>'rojo', 0=>'x'] // array_merge_recursive: si ambas claves tienen arrays, los fusiona en profundidad $config1 = ['db' => ['host' => 'localhost']]; $config2 = ['db' => ['port' => 5432]]; array_merge_recursive($config1, $config2); // ['db'=>['host'=>'localhost','port'=>5432]] // array_replace: como merge pero SIEMPRE sobrescribe (incluidas claves numéricas) array_replace($a, $b); // ['color'=>'azul', 0=>'y'] array_replace_recursive($config1, $config2); // array_pad: rellena hasta un tamaño mínimo array_pad([1, 2], 5, 0); // [1,2,0,0,0] array_pad([1, 2], -5, 0); // [0,0,0,1,2] (relleno al inicio)
| Función | Claves numéricas | Claves string duplicadas | Recursividad |
|---|---|---|---|
array_merge | Reindexa | Gana el último | Opcional (_recursive) |
+ | Conserva | Gana el primero | No |
array_replace | Sobrescribe por índice | Gana el último | Opcional (_recursive) |
En la práctica, array_merge suele ser la opción por defecto para unir listas o configuraciones, mientras que + es útil cuando quieres aplicar valores por defecto sin sobrescribir lo que ya estaba definido.
9. Extraer y dividir
A veces no se necesita el array completo sino un fragmento de él, o dividirlo en bloques de tamaño fijo para procesarlo por partes —por ejemplo, para paginar resultados o enviar lotes a una cola—. array_slice y array_splice suelen confundirse porque suenan parecido, pero se comportan de forma muy distinta.
$letras = ['a', 'b', 'c', 'd', 'e']; // array_slice: extrae un tramo SIN modificar el original array_slice($letras, 1, 3); // ['b','c','d'] array_slice($letras, -2); // ['d','e'] (desde el final) array_slice($letras, 1, 3, true); // conserva las claves originales // array_splice: extrae Y modifica el array original (puede insertar) $copia = $letras; $eliminados = array_splice($copia, 1, 2); // $copia queda ['a','d','e'] array_splice($copia, 1, 0, ['X', 'Y']); // inserta sin eliminar // array_chunk: divide en trozos de tamaño N array_chunk($letras, 2); // [['a','b'], ['c','d'], ['e']] array_chunk($letras, 2, true); // conserva las claves originales
En resumen: usa array_slice cuando solo necesites leer una parte del array sin tocar el original, y array_splice cuando además quieras eliminar o insertar elementos directamente en él.
10. Claves y valores
Estas funciones permiten trabajar con la estructura del array en sí —sus claves, sus valores o ambos por separado— en lugar de con los datos que contiene. Son especialmente útiles al transformar arrays de registros, como resultados de una consulta, en estructuras más manejables.
$persona = ['id' => 1, 'nombre' => 'Ana', 'edad' => 30];
array_keys($persona); // ['id','nombre','edad']
array_keys([1, 2, 1, 3], 1); // [0, 2] -> índices donde el valor es 1
array_values($persona); // [1,'Ana',30] (reindexa 0..n-1)
array_flip($persona); // invierte clave <-> valor
array_count_values(['a','b','a','c','a']); // ['a'=>3,'b'=>1,'c'=>1]
// array_column: extrae una "columna" de un array de arrays/objetos
$usuarios = [
['id' => 1, 'nombre' => 'Ana'],
['id' => 2, 'nombre' => 'Luis'],
];
array_column($usuarios, 'nombre'); // ['Ana','Luis']
array_column($usuarios, 'nombre', 'id'); // [1=>'Ana', 2=>'Luis'] (indexado por otra columna)
array_column($usuarios, null, 'id'); // reindexa el array completo por 'id'array_column es especialmente valiosa al trabajar con resultados de una consulta a base de datos, ya que evita bucles manuales para reorganizar filas en listas simples o en arrays indexados por un identificador.
11. Matemáticas y agregación
Cuando un array contiene números, PHP incluye funciones directas para obtener totales, productos o extremos sin necesidad de recorrerlo manualmente, lo que además suele ejecutarse más rápido que un bucle escrito a mano.
$numeros = [4, 8, 15, 16, 23, 42]; count($numeros); // 6 (alias: sizeof) array_sum($numeros); // 108 array_product($numeros); // producto de todos los elementos min($numeros); // 4 max($numeros); // 42 // count() con arrays multidimensionales count($matriz, COUNT_RECURSIVE); // cuenta también los sub-elementos
Estas funciones ignoran las claves y operan solo sobre los valores, así que conviene asegurarse de que el array no mezcle tipos no numéricos antes de usarlas, o los resultados pueden no ser los esperados.
12. Comparación: diff, intersect, unique
Estas funciones responden a preguntas como “¿qué hay en un array que no está en otro?” o “¿qué tienen en común?”, y siempre hay que decidir si la comparación debe hacerse por valor, por clave o por ambos a la vez.
php
$a = ['a' => 1, 'b' => 2, 'c' => 3]; $b = ['a' => 1, 'b' => 20]; array_diff($a, $b); // compara solo VALORES: ['b'=>2,'c'=>3] array_diff_key($a, $b); // compara solo CLAVES: ['c'=>3] array_diff_assoc($a, $b); // compara clave Y valor juntos: ['b'=>2,'c'=>3] array_udiff($a, $b, fn($x, $y) => $x <=> $y); // diff con callback de comparación array_intersect($a, $b); // valores presentes en ambos: ['a'=>1] array_intersect_key($a, $b); // claves presentes en ambos: ['a'=>1,'b'=>2] array_intersect_assoc($a, $b); // clave Y valor coinciden: ['a'=>1] array_unique([1, '1', 2, 2, 3]); // [1, 2, 3] (compara como string por defecto)
array_unique() compara los valores convirtiéndolos a string por defecto (SORT_STRING), lo que puede dar resultados inesperados con tipos mixtos; para objetos o comparaciones numéricas estrictas, es habitual combinarlo con array_map/serialize o escribir la deduplicación a mano.
13. Desestructuración
La desestructuración permite extraer varios valores de un array y asignarlos a variables individuales en una sola línea, algo especialmente útil al recorrer colecciones de pares o al trabajar con resultados que combinan varios campos relacionados.
// list() clásico
list($a, $b) = [1, 2];
// Sintaxis corta equivalente (recomendada)
[$a, $b] = [1, 2];
// Saltar elementos
[, $segundo, , $cuarto] = [1, 2, 3, 4];
// Desestructurar por clave
['nombre' => $nombre, 'edad' => $edad] = ['nombre' => 'Ana', 'edad' => 30];
// Anidada
[[$a, $b], [$c, $d]] = [[1, 2], [3, 4]];
// Muy común en foreach con arrays de pares
$puntos = [[0, 0], [1, 2], [3, 4]];
foreach ($puntos as [$x, $y]) {
echo "($x, $y)\n";
}La desestructuración es puramente sintáctica: no crea copias significativas y funciona igual de bien con arrays devueltos directamente por una función, sin necesidad de guardarlos primero en una variable intermedia.
14. Operador spread (...)
El operador ... permite “desempaquetar” un array en los argumentos de una función o en los elementos de otro array literal, evitando en muchos casos comunes tener que recurrir a array_merge() o a listas de argumentos construidas a mano.
// En llamadas a función (desde PHP 5.6)
function suma($a, $b, $c) { return $a + $b + $c; }
$valores = [1, 2, 3];
suma(...$valores);
// En array literals (desde PHP 7.4)
$parte1 = [1, 2];
$parte2 = [3, 4];
$todo = [...$parte1, ...$parte2, 5]; // [1,2,3,4,5]
// Spread con CLAVES STRING dentro de array literals: requiere PHP 8.1+
$defaults = ['color' => 'azul', 'tamaño' => 'M'];
$config = [...$defaults, 'color' => 'rojo']; // ['color'=>'rojo','tamaño'=>'M']Antes de PHP 8.1, hacer spread de un array con claves string dentro de un array literal ([...$asociativo]) lanzaba un error fatal; solo funcionaba con claves numéricas. Desde PHP 8.1 esto ya es válido y las claves posteriores sobrescriben a las anteriores, igual que con array_merge.
15. Arrays multidimensionales
Un array puede contener otros arrays como valores, lo que permite modelar estructuras jerárquicas como matrices, árboles o configuraciones anidadas. Acceder y construir este tipo de arrays con seguridad requiere prestar especial atención a los índices que podrían no existir.
$matriz = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
echo $matriz[1][2]; // 6
foreach ($matriz as $fila) {
foreach ($fila as $celda) {
echo $celda . ' ';
}
}
// Acceso seguro a rutas anidadas (evita warnings de índice inexistente)
$valor = $config['db']['credenciales']['host'] ?? 'localhost';
// array_multisort: ordena varias columnas relacionadas a la vez
$datos = ['edad' => [30, 25, 40], 'nombre' => ['Ana', 'Luis', 'Eva']];
array_multisort($datos['edad'], $datos['nombre']);
// Construir estructuras anidadas dinámicamente
$arbol = [];
$arbol['a']['b']['c'] = 'hoja'; // PHP crea automáticamente los niveles intermediosEl operador ?? (null coalescing, PHP 7+) es la forma estándar de leer claves potencialmente inexistentes sin generar warnings; ??= (PHP 7.4+) permite asignar solo si la clave no existe: $config['tema'] ??= 'claro';.
16. Novedades PHP 8.x en arrays
Las versiones 8.0, 8.1 y 8.4 introdujeron cambios que afectan directamente a cómo se trabaja con arrays: desde funciones completamente nuevas hasta comportamientos que interactúan con otras características modernas del lenguaje, como los enums o las propiedades readonly.
array_is_list() — PHP 8.1
Determina si un array es una lista: claves enteras, secuenciales, empezando en 0 y en orden. Sustituye a los típicos array_keys($arr) === range(0, count($arr) - 1).
php
array_is_list([1, 2, 3]); // true array_is_list([0 => 'a', 1 => 'b']); // true array_is_list([1 => 'a', 0 => 'b']); // false (orden incorrecto) array_is_list(['x' => 1]); // false (clave no numérica) array_is_list([]); // true (caso especial: la lista vacía cuenta como lista)
Es útil, por ejemplo, al serializar a JSON, para decidir si un array debe representarse como [...] o como {...}.
Spread con claves string en array literals — PHP 8.1
Ya cubierto en la sección 14.
readonly properties y arrays — PHP 8.1 (gotcha)
Una propiedad readonly que contiene un array no puede mutarse “por dentro” tras la construcción: no se puede hacer $this->items[] = $x fuera del constructor, porque eso reasigna la propiedad.
final class Coleccion
{
public function __construct(
public readonly array $items = [],
) {}
}
$c = new Coleccion([1, 2]);
// $c->items[] = 3; // Error: no se puede modificar una propiedad readonlyEnums como claves de array — PHP 8.1 (gotcha)
Los enum cases no pueden usarse directamente como claves de array (las claves solo admiten int o string). Hay que usar ->value (en backed enums) o ->name.
enum Estado: string { case Activo = 'activo'; case Inactivo = 'inactivo'; }
$contador = [
Estado::Activo->value => 10,
Estado::Inactivo->value => 3,
];WeakMap — PHP 8.0 (no es un array, pero resuelve lo mismo con objetos)
Un WeakMap es una estructura similar a un array asociativo, pero cuyas claves son objetos y no impiden que el recolector de basura los libere cuando ya no se usan en otro lugar. Un array normal usado como caché objeto => datos retendría el objeto en memoria para siempre; WeakMap no.
$cache = new WeakMap();
class Usuario { public function __construct(public string $nombre) {} }
$u = new Usuario('Ana');
$cache[$u] = ['calculo_pesado' => 123];
echo $cache[$u]['calculo_pesado']; // 123
echo count($cache); // 1
unset($u); // si no hay otras referencias, PHP libera el objeto
// y su entrada desaparece automáticamente de $cacheCasos típicos: cachés asociadas a instancias, metadatos de objetos, ORMs que anotan estado interno sin evitar que el objeto se destruya.
Named arguments y arrays — PHP 8.0
No modifican los arrays en sí, pero cambian cómo se llaman funciones que los reciben, mejorando la legibilidad de funciones como array_fill:
array_fill(start_index: 0, count: 3, value: 'x');
match como reemplazo de callbacks en array_map/filter — PHP 8.0
$etiquetas = array_map(
fn($estado) => match ($estado) {
'activo', 'pendiente' => 'visible',
'inactivo' => 'oculto',
default => 'desconocido',
},
$estados
);array_find(), array_find_key(), array_any(), array_all() — PHP 8.4
Cuatro funciones nuevas que evitan escribir bucles manuales para buscar o comprobar condiciones. El callback recibe (valor, clave).
$productos = [
['nombre' => 'Teclado', 'precio' => 45],
['nombre' => 'Monitor', 'precio' => 200],
['nombre' => 'Mouse', 'precio' => 15],
];
// array_find: devuelve el primer VALOR que cumple la condición, o null
$caro = array_find($productos, fn($p) => $p['precio'] > 100);
// ['nombre' => 'Monitor', 'precio' => 200]
// array_find_key: devuelve la primera CLAVE que cumple la condición, o null
$indice = array_find_key($productos, fn($p) => $p['precio'] > 100); // 1
// array_any: ¿al menos un elemento cumple la condición?
$hayCaro = array_any($productos, fn($p) => $p['precio'] > 100); // true
// array_all: ¿todos los elementos cumplen la condición?
$todosBaratos = array_all($productos, fn($p) => $p['precio'] < 50); // falseAntes de PHP 8.4, esto requería combinar array_filter + acceso al primer elemento, o un foreach con una bandera booleana; estas funciones cortocircuitan la iteración en cuanto encuentran el resultado.
Estas novedades no sustituyen a las funciones clásicas: lo habitual es seguir usando array_map/array_filter para transformaciones normales y reservar array_find/array_any/array_all para búsquedas puntuales que antes exigían un foreach manual.
17. JSON y serialización
Los arrays son el puente natural entre PHP y los formatos de intercambio de datos: JSON, muy usado en APIs, y el formato de serialización propio de PHP, habitual en cachés y en el manejo de sesiones.
$datos = ['nombre' => 'Ana', 'activo' => true, 'tags' => ['php', 'web']];
$json = json_encode($datos, JSON_PRETTY_PRINT);
$decodificado = json_decode($json, true); // true = como array asociativo (no stdClass)
// Un array "lista" se codifica como [...], uno asociativo como {...}
json_encode([1, 2, 3]); // "[1,2,3]"
json_encode(['a' => 1, 'b' => 2]); // '{"a":1,"b":2}'
// serialize / unserialize: formato propio de PHP, útil para caché/sesiones
$plano = serialize($datos);
$original = unserialize($plano);Para APIs públicas usa siempre JSON; reserva serialize()/unserialize() para datos internos de PHP, ya que deserializar contenido proveniente de una fuente no confiable puede ser un riesgo de seguridad.
18. Casting y conversión entre arrays y objetos
A veces necesitas confirmar que una variable realmente es un array antes de operar sobre ella, o convertir entre arrays y objetos al integrar con código que no usa arrays de forma nativa —por ejemplo, resultados de PDO en modo objeto, o clases sencillas con propiedades públicas.
is_array($valor); // true si $valor es un array
gettype($valor); // 'array', 'object', 'integer', etc.
// De objeto a array
$objeto = (object) ['nombre' => 'Ana', 'edad' => 30];
$array = (array) $objeto; // ['nombre'=>'Ana', 'edad'=>30]
$array2 = get_object_vars($objeto); // resultado equivalente
// De array a objeto
$obj = (object) ['nombre' => 'Ana'];
echo $obj->nombre; // Ana
// stdClass explícito, útil al construir respuestas JSON con objetos vacíos {} en vez de []
$stdObj = new stdClass();
$stdObj->id = 1;El cast (array) sobre un objeto solo expone las propiedades públicas visibles desde el contexto actual; para acceder también a propiedades privadas o protegidas desde dentro de la propia clase, usa get_object_vars($this).
19. compact() y extract()
Estas dos funciones tienden un puente entre variables sueltas y un array asociativo: son muy comunes al pasar varias variables con nombre a una plantilla o vista, sin tener que construir el array a mano campo por campo.
$nombre = 'Ana';
$edad = 30;
$datos = compact('nombre', 'edad'); // ['nombre' => 'Ana', 'edad' => 30]
extract($datos); // crea/actualiza $nombre y $edad en el scope actual
// Uso típico: pasar variables con nombre a una plantilla
function render(string $vista, array $datos): void {
extract($datos);
include $vista; // dentro de la plantilla ya existen $nombre, $edad...
}extract() sobrescribe silenciosamente cualquier variable existente con el mismo nombre, así que conviene usarlo solo con arrays de origen controlado —como en motores de plantillas propios— y nunca con datos que vengan directamente del usuario.
20. Funciones variádicas
Cuando una función necesita aceptar un número variable de argumentos, PHP los agrupa internamente en un array; conocer cómo capturarlos permite escribir funciones flexibles sin llenar la firma de parámetros opcionales.
// Sintaxis moderna (recomendada): argumentos variádicos con ...
function sumarTodo(int ...$numeros): int {
return array_sum($numeros); // $numeros ya es un array
}
sumarTodo(1, 2, 3, 4); // 10
// Forma clásica, sin declarar los parámetros de antemano
function logEvento(): string {
$argumentos = func_get_args(); // array con todos los argumentos recibidos
return implode(' | ', $argumentos);
}
// Combinar variádicos con spread al llamar
$valores = [1, 2, 3];
sumarTodo(...$valores);La sintaxis ...$parametro en la definición de una función y el spread ...$array al llamarla son operaciones inversas: una empaqueta argumentos sueltos en un array, la otra desempaqueta un array en argumentos sueltos.
21. Invertir el orden: array_reverse()
Invertir el orden de un array es una operación pequeña pero frecuente, sobre todo al mostrar listas cronológicas en orden inverso (por ejemplo, “lo más reciente primero”).
$letras = ['a', 'b', 'c']; array_reverse($letras); // ['c', 'b', 'a'] (reindexa por defecto) array_reverse($letras, true); // conserva las claves originales $persona = ['nombre' => 'Ana', 'edad' => 30]; array_reverse($persona); // invierte el orden manteniendo las claves string
Con arrays indexados, recuerda pasar true como segundo argumento si necesitas conservar los índices originales; de lo contrario, array_reverse los reasigna de 0 en adelante, igual que hace array_merge.
22. Copia por valor: arrays en memoria
A diferencia de los objetos, los arrays en PHP se copian por valor: asignar un array a otra variable o pasarlo a una función crea, conceptualmente, una copia independiente, gracias a un mecanismo interno llamado copy-on-write que evita el costo real de copiar hasta que realmente hace falta.
$original = [1, 2, 3];
$copia = $original; // copia "por valor"
$copia[] = 4;
var_dump($original); // [1, 2, 3] -> sin cambios
var_dump($copia); // [1, 2, 3, 4] -> solo la copia cambió
function modificar(array $arr): array {
$arr[] = 99;
return $arr;
}
$numeros = [1, 2];
modificar($numeros);
var_dump($numeros); // [1, 2] -> la función no modifica el array original
function modificarPorReferencia(array &$arr): void {
$arr[] = 99;
}
modificarPorReferencia($numeros);
var_dump($numeros); // [1, 2, 99] -> ahora sí, gracias al "&"Internamente PHP no copia el array hasta que una de las dos variables lo modifica (copy-on-write), así que asignar o pasar arrays por valor es barato en la práctica; usa el operador & solo cuando de verdad necesites que la función modifique el array original.
23. Agrupar y pivotear datos
Un patrón muy común al procesar listas de registros —ventas, pedidos, logs— es agruparlos o sumarlos por alguna categoría, algo que normalmente se resolvería con GROUP BY en SQL pero que también se puede hacer directamente en PHP con array_reduce.
$ventas = [
['region' => 'Norte', 'monto' => 100],
['region' => 'Sur', 'monto' => 50],
['region' => 'Norte', 'monto' => 75],
];
// Agrupar los registros completos por región
$porRegion = array_reduce($ventas, function (array $acc, array $venta) {
$acc[$venta['region']][] = $venta;
return $acc;
}, []);
// ['Norte' => [...], 'Sur' => [...]]
// Sumar el monto total por región
$totalPorRegion = array_reduce($ventas, function (array $acc, array $venta) {
$acc[$venta['region']] = ($acc[$venta['region']] ?? 0) + $venta['monto'];
return $acc;
}, []);
// ['Norte' => 175, 'Sur' => 50]Este patrón evita traer librerías externas de colecciones solo para agrupar o sumar por categoría; combinado con ?? para inicializar el acumulador, cubre la mayoría de los casos de “agrupar por” que de otro modo se resolverían con una consulta SQL adicional.
24. Rendimiento y buenas prácticas
Más allá de conocer las funciones disponibles, escribir código eficiente con arrays implica algunas decisiones de diseño que marcan la diferencia sobre todo en scripts que procesan grandes volúmenes de datos.
- Evita
count()dentro de la condición de unforcuando el array no cambia de tamaño; guárdalo en una variable antes del bucle. isset()es más rápido quearray_key_exists()cuando no te importa distinguirnullde “no existe”.array_filter+array_mapen cadena son legibles pero recorren el array varias veces; para datasets grandes, un únicoforeachpuede ser más eficiente.- Pasar arrays grandes por referencia (
&$array) a funciones evita copias, pero PHP ya usa copy-on-write: un array solo se copia de verdad si se modifica, así que pasar por valor casi nunca es costoso salvo que sí lo modifiques dentro de la función. unset()explícito libera memoria antes de lo que lo haría el recolector de basura, útil en scripts de larga duración que procesan arrays enormes.- Prefiere funciones nativas (
array_map,array_filter,array_sum…) sobre bucles manuales: están implementadas en C y suelen ser más rápidas, además de más legibles. - Usa
array_is_list()en vez de comprobaciones manuales para decidir si tratar un array como lista o como diccionario antes de serializarlo.
Ninguna de estas prácticas exige reescribir código existente de golpe: son ajustes puntuales que conviene tener presentes al revisar código que procesa arrays grandes o que se ejecuta con mucha frecuencia.
25. Errores comunes (gotchas)
Estos son los errores con arrays que más aparecen en revisiones de código y en producción: comportamientos que no son evidentes a simple vista, pero que una vez conocidos se evitan con facilidad.
// 1) array_filter no reindexa
$pares = array_filter([1, 2, 3, 4], fn($n) => $n % 2 === 0); // [1=>2, 3=>4]
json_encode($pares); // {"1":2,"3":4} <- ¡no es una lista JSON!
$pares = array_values($pares); // arregla el problema
// 2) Comparación débil en in_array/array_search
in_array('abc', [0, 1, 2]); // true en PHP < 8 por comparación numérica de 'abc' == 0
// desde PHP 8 las comparaciones string/number cambiaron
in_array('abc', [0, 1, 2], true); // false, siempre seguro con comparación estricta
// 3) foreach por referencia sin unset() posterior
foreach ($arr as &$v) { $v *= 2; }
foreach ($arr as $v) { /* $v aquí sigue "enganchado" a la última referencia -> bug sutil */ }
unset($v); // SIEMPRE haz esto tras un foreach por referencia
// 4) Modificar un array mientras lo recorres con foreach (por valor)
// foreach itera sobre una COPIA, así que añadir elementos dentro del bucle no los visita.
// 5) array_merge vs + con claves numéricas
array_merge([5 => 'a'], [5 => 'b']); // [0=>'a', 1=>'b'] -> ¡reindexa las numéricas!
[5 => 'a'] + [5 => 'b']; // [5=>'a'] -> conserva la clave originalConocer estos patrones de antemano evita horas de depuración: casi todos los bugs relacionados con arrays en PHP caen en una de estas cinco categorías.
26. Cheat sheet final
Esta tabla resume de un vistazo qué función usar según la tarea, pensada como referencia rápida una vez que ya se conoce en detalle cada una de ellas, explicado en las secciones anteriores.
| Necesito… | Función |
|---|---|
| Crear una secuencia rápida | range() |
| Rellenar con un valor fijo | array_fill, array_fill_keys |
| Combinar claves y valores por separado | array_combine |
| Añadir/quitar al final | array_push, array_pop |
| Añadir/quitar al inicio | array_unshift, array_shift |
| Rellenar hasta un tamaño mínimo | array_pad |
| Comprobar si una clave existe | array_key_exists, isset |
| Buscar un valor | in_array, array_search |
| Buscar por condición | array_find, array_find_key (8.4) |
| ¿Alguno/todos cumplen? | array_any, array_all (8.4) |
| Primera / última clave | array_key_first, array_key_last |
| Recorrer con puntero interno | current, next, prev, reset, end, key |
| Transformar cada elemento | array_map |
| Filtrar elementos | array_filter |
| Reducir a un valor | array_reduce |
| Mutar in place (incluye anidados) | array_walk, array_walk_recursive |
| Ordenar por valor | sort, asort, usort |
| Ordenar por clave | ksort, uksort |
| Combinar arrays | array_merge, +, array_replace |
| Desempaquetar en llamadas o literales | operador ... (spread) |
| Cortar un tramo | array_slice (lectura), array_splice (mutación) |
| Dividir en trozos | array_chunk |
| Solo claves / solo valores | array_keys, array_values |
| Invertir clave-valor | array_flip |
| Contar ocurrencias de cada valor | array_count_values |
| Extraer una “columna” | array_column |
| Contar elementos | count / sizeof |
| Sumar / multiplicar | array_sum, array_product |
| Mínimo / máximo | min, max |
| Diferencias / intersección | array_diff*, array_intersect* |
| Diferencias con comparación personalizada | array_udiff, array_uintersect |
| Diferencias/intersección de claves con comparación personalizada | array_diff_ukey, array_intersect_ukey |
| Crear variables a partir de un array asociativo | extract() |
| Crear un array a partir de variables existentes | compact() |
| Invertir el orden de un array | array_reverse |
| Capturar argumentos variádicos | ...$parametro, func_get_args() |
| Convertir array ↔ objeto | (array), (object), get_object_vars |
| Verificar que una variable es un array | is_array |
| Agrupar/sumar registros por categoría | array_reduce (patrón “group by”) |
| Quitar duplicados | array_unique |
| Desestructurar valores en variables | list() / [$a, $b] = $arr |
| ¿Es una lista 0..n-1? | array_is_list (8.1) |
| Convertir a/desde JSON | json_encode, json_decode |
| Serializar/deserializar (formato PHP) | serialize, unserialize |
| Caché por objeto sin memory leak | WeakMap (8.0) |
Descarga los ejemplos
Descarga guia-arrays-php.zip: un único archivo ZIP con todos los ejemplos de las secciones de esta guía.
Conclusión
Los arrays son, con diferencia, la estructura de datos que más se usa en PHP, y esta guía cubrió el recorrido completo: desde crearlos y modificarlos, pasando por las familias de funciones que resuelven el 90% de los casos reales —transformación, combinación, comparación, agregación—, hasta las incorporaciones más recientes del lenguaje como array_is_list(), el spread con claves string y las funciones array_find/array_any/array_all de PHP 8.4.