Eloquent, which is Laravel’s ORM, has some really nice features. One of which is the [Eager Loading][eager]functionality that allows you to request all of the related records in one hit, to avoid having to makemultiple database calls for each iteration of a loop.
Let’s look at a simple example which returns the latest 10 blog posts, with tags Eager Loaded in one line:
$posts = PostsModel::with('tags')->whereNotNull('published') ->orderBy('published', 'desc') ->limit(10) ->get();
Now all we have to do is access $post->tags
for each of the $posts
and it’ll have the records we requirewaiting in memory, rather than needing to do another database query.
But there is a problem – what if we want to sort the tags?
The two options we have are:
- Sort the collection we retrieve from
$posts->tags
. - Sort the tags in the initial database query, before they are loaded into PHP.
Although #1 is a perfectly valid solution, #2 is much nicer and also likely faster since we’re making thedatabase do the sorting, which is something it does really well, instead of PHP.What we need to do here is update the Eager Loading definition to sort the tags when it retrieves them initially.
Luckily, we can use the Eager Load Constraints option to modify the query used to retrieve the eager loaded records.This makes it a piece of cake to sort the records, or even place further constraints on the eager loaded records.
So our example code now looks like this:
$posts = PostsModel::with(array( 'tags' => function ($query) { $query->orderBy('name', 'asc'); }))->whereNotNull('published') ->orderBy('published', 'desc') ->limit(10) ->get();
Now when we access $post->tags
for each of the $posts
, it will be loading sorted tags from memory,rather than directly from the database.
Seems pretty simple, really 🙂
One reply on “Sorting eager loaded records in Laravel's Eloquent.”
Great! That was exactly I was searching for a long time. The official Laravel docs are a little short in some aspects.