> Faqs > Ordenar los registros de una relación obtenidos al usar Eager Loading con with en Laravel

Ordenar los registros de una relación obtenidos al usar Eager Loading con with en Laravel

En Laravel es muy útil el mecanismo de Eager Loading para traer los modelos relacionados con otros modelos, de modo que te ahorras consultas SQL iterativas al servidor de base de datos, usando el método with de Query Builder al hacer la consulta.

$posts = Post::whereTagId($id)->with('comments')->orderBy('order')->get();

El caso es que los modelos relacionados los quisiera poder ordenar. Es decir, para el ejemplo de código anterior, quisiera ordenar los comentarios por fecha descendente.

¿Cómo podría conseguir eso? Es decir, ordenar los registros relacionados que se obtienen por Eager Loading, gracias al método with() de Eloquent.

Respuestas

Ordenar los modelos adquiridos a través de las relaciones en Eloquent se puede hacer de dos maneras distintas.

  1. La primera consiste simplemente en declarar la relación en el modelo, aplicando el orden directamente en ella. Es decir, al hacer el método que devuelve los modelos relacionados con algo como hasMany() o belongsToMany() usas los métodos adicionales de Laravel Query Builder para conseguir el orden deseado.

Por ejemplo puedes ver este código en el que se define la relación de tags y luego los tags se ordenan por el título.

public function tags() {
    return $this->hasMany('App\Tag')->orderBy('title');
}

Este mecanismo tiene la comodidad que, cada vez que se realice la consulta para obtener los modelos relacionados, se ordenará por el título. Ya sea cuando usas with para aplicar Eager Loading o carga anticipada, como cuando accedas a los datos una vez realizada la consulta por lazy loading.

$posts = Post::with('tags')->get();
  1. Como alternativa, podemos hacer esto mismo directamente cuando hacemos la consulta Eager Loading, con el with().

En este caso la relación con el modelo puede quedar simplemente definida sin indicar ningún orden:

public function tags() {
    return $this->hasMany('App\Tag');
}

Y al hacer la consulta para traerte los modelos relacionados con with, entonces aplicas el orden deseado:

$posts = Post::with(['tags' => function($query) {
    $query->orderBy('title')
})->get();

Este segundo mecanismo da un poco más de trabajo, puesto que tienes que especificar el orden cada vez que haces la consulta con el método with(). Sin embargo es más versátil, porque puedes hacer consultas donde los modelos relacionados podrán estar ordenados de un modo o de otro, según se necesite en cada caso.

Miguel Angel
3145 140 209 17
Una respuesta muy completa. Muchas gracias!