> Manuales > Manual de Laravel

Qué son las colecciones de Laravel, por qué son importantes. Qué podemos hacer con colecciones, con ejemplos de uso de los métodos disponibles y consejos a la hora de usar colecciones en las aplicaciones.

Colecciones en Laravel

En este artículo vamos a abordar un tema que se encuentra en Laravel por todas partes, y por extensión en la programación en general. Se trata del trabajo en general con grupos de elementos, que en Laravel se realiza mediante las colecciones, estructura en la que nos apoyamos constantemente para el desarrollo de aplicaciones.

La cantidad de cosas que podemos hacer con colecciones es enorme y Laravel ofrece muchas utilidades para facilitar el tratamiento de los conjuntos de elementos. En este artículo aprenderemos mejor qué son las colecciones y veremos algunos casos de uso con ejemplos prácticos.

Hay muchas cosas que debes aprender sobre Colecciones en Laravel. Las hemos resumido en los siguientes puntos.

Qué son las colecciones de Laravel

Las colecciones en Laravel son algo así como una envoltura sobre los arrays de datos comunes que nos ofrece PHP, aportando un conjunto de funcionalidades mayor, lo que nos permite trabajar con conjuntos de datos a más alto nivel, produciendo un código más expresivo y sencillo. Proporcionan una gran cantidad de métodos útiles para operar con los conjuntos de datos, algo muy necesario en las aplicaciones, sean del tipo que sean.

En Laravel las colecciones son implementadas a través de la clase Illuminate\Support\Collection pero raramente hacemos la instanciación de objetos de esta clase. En la mayoría de los casos las colecciones nos son entregadas a nosotros cuando estamos desarrollando y accedemos a cualquier conjunto de elementos, como los registros de una base de datos.

Por qué son importantes las colecciones

Las colecciones son muy importantes en la programación ya que habitualmente tenemos que trabajar con conjuntos de datos y es necesario realizar operaciones sobre ellos, como filtrados, transformaciones, iteraciones, búsquedas, etc. Por ello, es esencial contar con unas estructuras potentes que provean de diversas operaciones de alto nivel para trabajar con los datos.

Por ejemplo, un lugar donde están muy presentes las colecciones es en el uso de bases de datos. Al acceder a la información de las bases de datos en Laravel usamos funciones del ORM que nos devuelven distintas filas de registros. Esas filas Laravel las entrega en colecciones, de modo que podemos hacer una cantidad de operaciones muy amplia sobre ellas. Gracias a que Laravel Eloquent devuelve sus datos en "Collections", obtienes muchos beneficios sobre los arrays crudos de PHP, como la capacidad de encadenar métodos útiles sobre los datos, la simplificación del código, así como una cantidad enorme de operaciones para manipular los datos.

Por supuesto, nosotros también podemos usar las colecciones para albergar datos, de modo que podemos beneficiarnos de toda su potencia a la hora de manipularlos y trabajar con ellos.

Colecciones devueltas por el ORM Eloquent

Creo que el ejemplo más habitual de uso de colecciones lo tenemos cuando trabajamos con el ORM de Laravel, Eloquent. Cualquier conjunto de registros, cuando hacemos una consulta de selección, nos lo entregan en colecciones.

Por ejemplo veamos esta consulta:

$websites = Site::where('domain', 'com')->get();

En el momento que hacemos get() sobre una query, Laravel procesa la consulta sobre el motor de la base de datos y nos devuelve una colección. Esa colección tendrá el conjunto de registros resultante de hacer la query anterior.

Por si no queda claro, en la sentencia anterior:

Crear colecciones desde cero

Por supuesto, nosotros también podemos crear colecciones. Como decía antes, para crear colecciones no instanciamos el objeto de la clase Collection, sino que lo común es usar el helper collect().

Mediante este código podemos crear una colección vacía.

$miColeccion = collect([]);

Como podrás imaginar, también podemos crear colecciones donde ya tenemos elementos.

$miColeccion = collect([2,1,7]);

Las colecciones son iterables

Las colecciones de Laravel las podemos tratar en algunos casos como si fueran arrays. Por ejemplo podemos iterar por ellas para realizar cualquier tipo de operación con cada uno de los elementos de la colección.

Para ello usamos bucles de PHP comunes como foreach.

$ciudades = collect(['Huelva', 'Murcia', 'Zamora', 'Logroño']);
foreach( $ciudades as $ciudad) {
    // hacer algo con $ciudad
}

Si enviamos la colección a una vista es posible iterar por ella en un template Blade, en este caso con el bucle @foreach de Blade.

@foreach ($ciudades as $ciudad)
    <p>{{ $ciudad }}</p>    
@endforeach

Métodos de colecciones

La potencia de las colecciones reside en la cantidad de métodos que Laravel te ofrece para trabajar con ellas. Entre otras muchas cosas encontramos métodos para hacer operaciones como estas:

Enseguida veremos ejemplos de uso de algunos de estos métodos. Pero si no lo has hecho ya te recomendamos entrar en la la documentación de Laravel, donde podrás ver todos los métodos disponibles en las colecciones. Observaremos que hay montones de ellos.

Un consejo que podemos dar ya mismo es que siempre, antes de intentar realizar cualquier procedimiento automatizado para tratar los datos de las colecciones, investigues si existe algún método disponible que lo realice.

Los métodos de colecciones son encadenables

Por si fuera poco, es posible combinar varios métodos de colecciones ya que en Laravel la mayor parte de los métodos de colecciones devuelven otras colecciones.

Por ejemplo, si añadimos un registro a una colección con el método push(), además de añadir ese registro, Laravel nos devolverá la colección resultante, de modo que podremos usarla para seguir encadenando otros métodos de colecciones.

Aquí tenemos un ejemplo de varios métodos de colección encadenados. Se ejecutarán en secuencia, transformando la colección a cada paso.

$ciudades = $ciudades->reject('Murcia')->push('Almendralejo')->sort();

Después de ejecutar estos métodos, la colección $ciudades que teníamos antes habrá pasado a tener los siguientes valores ordenados alfabéticamete. Habremos quitado "Murcia" pero agregado "Almendralejo".

Convertir colecciones a arrays

Hay veces que necesitamos tener un array en vez de una colección. Por ejemplo podrías estar usando una librería que espera recibir un array por parámetro, o quizás reutilizar un código tuyo donde se esperan métodos de arrays de PHP.

Si por cualquier cuestión necesitamos pasar desde una colección a un array podemos hacerlo fácilmente. Para ello generalmente usamos el método all() de las colecciones.

$arrayCiudades = $ciudades->all();

Pero también existe un método llamado toArray(). La diferencia es que toArray() convierte a array también los objetos que puedes tener como valores de la colección, es decir, hace un trabajo de conversión de la colección principal y de las colecciones que pueda tener como valores dentro.

Generalmente el método all() es el que querrás hacer, pero está bien conocer ambos.

Ejemplos de trabajo con colecciones

Sería infinita la lista de cosas que podrías llegar a hacer con colecciones. Vamos a ver algunos ejemplos sencillos de código.

Comenzaremos por un ejemplo sencillo pero esencial, que consiste en saber el número de elementos de una colección.

$collection = collect([1, 52, 3, 8, 15]);
$collection->count(); // devuelve 5

Otro ejemplo muy sencillo lo tenemos en el método sum() que nos permite obtener la suma de los valores de una colección.

$collection = collect([1, 2, 3, 4, 5]);
$total = $collection->sum(); // $total valdrá 15

Este ejemplo se podría complicar un poco si tenemos una colección de elementos arrays y donde el precio está en una de las casillas de cada array.

$products = collect([
    ['name' => 'Mesa', 'price' => 200],
    ['name' => 'Silla', 'price' => 100],
    ['name' => 'Librería', 'price' => 150],
    ['name' => 'Armario', 'price' => 100]
]);
$averagePrice = $products->avg('price');

Existen funciones para otras operaciones matemáticas como la media que puedes obtener con avg(), max(), min(), etc.

Hay métodos de colecciones un poco más complejos, por ejemplo los que permiten realizar filtrados o transformaciones. Para usarlos generalmente tenemos que enviar funciones como parámetro y las funciones se ejecutarán para cada elemento de la colección.

En el siguiente ejemplo vamos a mostrar cómo hacer una nueva colección que tenga solamente las ciudades cuyo nombre contenga la letra "o".

$ciudadesConO = $ciudades->filter(function ($ciudad) {
    return strpos($ciudad, 'o') !== false;
});

Colecciones con índices de cadena

Por simplicidad, todos los ejemplos anteriores los hemos hecho con colecciones que tenían índices numéricos pero es igualmente común trabajar con colecciones que tengan índices de cadenas, que se asemejan a los arrays asociativos de PHP.

$person = collect([
    'name' => 'Miguel Angel Alvarez', 
    'email' => 'miguel@example.com',
    'telephone' => '101 101 101',
]);

Si necesitamos hacer un recorrido a una colección y obtener tanto sus índices como sus valores lo haremos de manera similar a como se haría con arrays asociativos de PHP de toda la vida.

@foreach ($person as $key => $value)
    <p>{{ $key }}: {{ $value }}</p>    
@endforeach

Existen muchos métodos específicos para colecciones que tienen índices alfanuméricos. Por ejemplo, podríamos ordenar una colección por sus llaves en lugar de sus valores.

$person = $person->sortKeys();

Hay muchos métodos de colecciones que no modifican la colección original, sino que crean una nueva colección modificada, por lo tanto para actualizar la colección original tendríamos que hacer una asignación como en el ejemplo anterior.

Podríamos eliminar un elemento de la colección indicando su llave:

$collection->forget('name');

Consejos al usar colecciones de Laravel

Como decía, sería inacabable el artículo si queremos mostrar ejemplos concretos de cada método y cada situación donde podríamos utilizarlo. Por eso vamos a finalizar simplemente aportando algunos consejos interesantes cuando trabajamos con colecciones en Laravel.

Consejos respecto a colecciones y Eloquent

Ten en cuenta que cuando usas el ORM Eloquent para ejecutar consultas de selección los datos que se entregan están contenidos en colecciones, esto te puede dar pie a encadenar diversos métodos que permitan seguir trabajando con los datos de las consultas y transformándolos en las estructuras que necesites en tus aplicaciones.

Sin embargo, tienes que ser especialmente cuidadoso con los datos que traes y minimizar las operaciones con colecciones que requerirán más tiempo y memoria que si las realizas con el motor de la base de datos.

Para ver esto quiero mostrar un par de alternativas de código.

$activeUsers = User::where('active', 1)->orderBy('created_at)->get();
$activeUsers = User::where('active', 1)->get()->sortBy('created_at');

Estos dos códigos deberían dar los mismos resultados. Sin embargo uno de ellos podría ser mejor, especialmente si pensamos que podrían haber decenas o cientos de miles de usuarios en una base de datos.

La clave la tienes en el momento en el que llamas a get(), que es cuando se produce la consulta y se crea la colección. Mientras que el primero solicita al motor de la base de datos que haga la selección y devuelva los usuarios ya ordenados, el segundo recibe toda la lista de usuarios sin ordenar y luego ordena los registros usando el método sortBy de la colección. Esta segunda alternativa puede ser mucho peor, especialmente cuando tenemos muchos usuarios, ya que el motor de la base de datos está optimizado para realizar estas operaciones de ordenación, mucho más que el lenguaje PHP.

Miguel Angel Alvarez

Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...

Manual