Array, collection y eloquent collection en Laravel

Publicado por Andrés López

Array, collection y eloquent collection en Laravel

Cuando comencé a programar en Laravel (que también comencé a codificar en PHP) recuerdo escribir código sin mucha idea de lo que hacia, pero que de alguna manera funcionaba, no sabía diferencia entre tipos de datos u objetos; para mí todo era lo mismo.

Recuerdo intentar acceder a propiedades de arreglos cuando me conectaba a APIs:

$data = json_decode($response);

$data[0]['name']; // FATAL ERROR

O llamar al método toArray (ni siquiera sabía de donde venía ese método) solo para poder trabajar con arreglos:

$users = DB::table('users')->get()->toArray();

$users[0]['name'];

Después aprendi que si llamabas a json_decode con el segundo parámetro true podia acceder a los valores mediante la notación [ ] y termine usando los modelos de Eloquent de una manera bastante extraña y fea 🤢:

$user = json_decode(json_encode(User::first()), true);

$user['name'];

Llego un punto en que mi código era inmantenible, practicamente era más fácil refactorizar todo que intentar modificarlo, lo mejor que pude hacer fue leer, leer y leer, principalmente la documentación oficial de laravel y algún que otro tutorial que me encontraba por internet, mi primer acercamiento fue diferenciar array de un object

Siempre tuve dudas de porque a veces funcionaba el de arriba y en otras el de abajo:

$user = $response->product;

$user = $response['product'];

PHP Array y PHP Object

La principal diferencia ente estos 2 tipos de datos es la manera en que accesas a su información.

Por un lado tenemos un Array:

$data = [];

$data['name']; // siempre se accede mediante []

Y el otro un Object:

$data = new stdClass();  // manera 'oficial' de crear un Object
// Hay muchas maneras de crear un object, habitualmente usando esta función es cuando comunmente los creamos
$data = json_decode($response);

$data->name; // siempre se accede mediante ->

en comparación los arrays se empiezan a quedar cortos pues no se puede hacer más que utilizar programación secuencial (de arriba a abajo).

Y aquí es donde la cosa se pone curiosa, pues PHP tiene funciones practicamente para todo, solo que algunos toma parametros por valor y en otras ocasiones lo toma por referencia, lo cual nos deja con un código muy raro y con poca legibilidad:

// limpiar el array para quedarnos solo con los ints, ordenados de menor a mayor

$data = [4, '', 0, 'test', 32];
$data = array_filter($data, fn($item) => is_numeric($item));
asort($data);

echo $data;

Laravel Collection

La comunidad de Laravel se percató de este dilema en PHP y comenzó a crear la clase para manejar arreglos Illuminate\Support\Collection, aquí retomamos el concepto de Object, pues cada que usemos esta clase obtendremos un Object con el que podemos interactuar:

use Illuminate\Support\Collection;

$data = [4, '', 0, 'test', 32];

$data = Collection::make($data); // esta es una forma muy elegante de hacerla 
$data = collect($data); // y esta es la versión corta con helper
// ambos hacen lo mismo

Y ahora usando los métodos de esta clase que puedes consultar en la documentación oficial es más sencillo procesar esta información de manera legible:

// limpiar el array para quedarnos solo con los ints, ordenados de menor a mayor

$data = [4, '', 0, 'test', 32];

echo Collection::make($data)
                ->filter(fn($item) => is_numeric($item))
                ->sort()
                ->all(); // este método es solo para obtener el arreglo y no el Object

Eloquent Collection

¿Y que pasa con los modelos? Bueno, aquí cambia un poco la historia, pues cada que hagas una consulta a la base de datos usando los modelos de eloquent y usemos el método ->get() obtendremos una Object de Illuminate\Database\Eloquent\Collection:

$users = User::where('name', 'LIKE', "{$search}%")->get();

Para se honesto, si vuelves a leer la documentación oficial te darás cuenta que puedes utilizar los mismos métodos que ya revisamos previamente, solo que hay una pizca de sazón en este nuevo platillo, y para ello hay que entender como esta construido una Eloquent Collection

  1. Es una herencia de Illuminate\Support\Collection:
namepace Illuminate\Database\Eloquent;

class Collection extends \Illuminate\Support\Collection
{
    ...
}
  1. Estamos lidiando siempre con in solo modelo por Eloquent Collection
  2. Hay nuevos método relacionados a los modelos
  3. Los modelos cuentan con relaciones Eloquent
  4. Es una Collection enfocada a la interacción con base de datos

Tomando en cuenta lo anterior podrás ver que hay nuevos métodos que nuevamente, puedes consultar en la documentación oficial:

$users = User::get();

$user->load('comments'); // carga una relación

echo $users->modelKeys(); //[1, 2, 3, 4, 5]

¿Cómo diferencio entre Array, Object, Collection y Eloquent Collection?

La mejor respuesta que te pueda dar es: práctica. Conforme más programes en Laravel y PHP más fácil te será ir diferenciando ente un tipo de dato y otro, aunque te puedo dar un checklist


// retornan instancias de \Illuminate\Support\Collection
collect($data);
Collection::make($data);
DB::table($table)->get();

// retornn instancias de \Illuminate\Database\Eloquent\Collection
User::get();
$user->comments()->get();
$user->load('posts')->posts;

// arrays 1005 seguro
array(1, 2, 3, 4, 5);
[1, 2, 3, 4, 5];

// quiza arrays, quiza objects
$values = json_decode($data, false);
$values = json_decode($data, true);

// usa esta función para quitarte de dudas
gettype($values);

Espero te haya servido esta información, llevo muchos años trabajando con Laravel, esta es la primera vez que público mi conocimiento, tengo mucho más que compartir en futuras publicaciones de mi blog, gracias :)

Andrés López

Andrés López

Gran fan de Laravel, entusiasta de Vue y escritor de cualquier cosa que suene interesante