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.
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
- Por qué son importantes las colecciones
- Colecciones devueltas por el ORM Eloquent
- Crear colecciones desde cero
- Las colecciones son iterables
- Métodos de colecciones
- Los métodos de colecciones son encadenables
- Convertir colecciones a arrays
- Ejemplos de trabajo con colecciones
- Colecciones con índices de cadena
- Consejos al usar colecciones de Laravel
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:
- La parte
Site::where('domain', 'com')
es una query - El método
get()
ejecuado sobre la query es el que provoca que la consulta se ejecute - El resultado de esa sentencia finalzada en el método
get()
devuelve los valores en una colección.
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:
- Añadir registros con
push
o quitarlos con métodos comopull
- Transformar los datos con métodos como
map
otransform
. - Filtrar datos, con los métodos
filter
oreject
, entre otros. - Ordenar colecciones usando
sortBy
sortByDesc
,sortKeys
... - Agrupar elementos de diversos modos, como hacemos con
groupBy
. - Realizar operaciones de acumulación, medias, etc., con métodos como
sum
,avg
... - Extraer datos específicos y quedarse solamente con ellos, como
pluck
.
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.
- Siempre que puedas, usa colecciones en lugar de arrays, ya que te permitirá trabajar con todas las funciones de utilidad que Laravel ofrece. Es verdad que trabajar con colecciones puede consumir más memoria que trabajar con arrays elementales, pero esto solo sería relevante si tienes colecciones especialmente grandes. Generalmente preferimos priorizar un código sencillo y claro que el rendimiento.
- En caso que tengas colecciones lo suficientemente grandes para provocar un impacto en la memoria y el rendimiento, te recomendamos investigar la clase
LazyCollection
de Laravel. Las colecciones perezosas proporcionan un método iterativo para trabajar con grandes conjuntos de datos. - Aprende a encadenar métodos de colecciones y utilizar algunos especialmente útiles como
map
,reduce
,filter
,flatMap
,search
.
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...