Ordering in Laravel is pretty straightforward, but you can use a few other techniques to make the most of Eloquent's ordering abilities. Let's cover everything you should know about ordering queries with Laravel!
The most basic ordering with Eloquent starts with the orderBy
method. Here's what it looks like:
$posts = Post::orderBy('published_at', 'desc')->get();
The first argument (published_at
here) is the column you want to order by. This can be any column type. In this case, it's a datetime.
The second argument is the direction you want to sort in (either desc
for descending or asc
for ascending).
So, if you wanted to fetch all posts and show the latest first, you'd order by the created_at
or published_at
date in descending (desc
) order.
But wait, there's even a method for sorting specifically in descending order if you prefer this to passing in a second argument:
$posts = Post::orderByDesc('published_at')->get();
Most of the time, you'll order by the latest or oldest records. Laravel has some built-in scopes that make this much easier to write.
To order with the latest at the top:
$posts = Post::latest()->get();
To order with the oldest at the top:
$posts = Post::oldest()->get();
By default, these two scopes will use the created_at
date, but you can pass in the column you'd like to use:
$posts = Post::latest('published_at')->get();
Behind the scenes, these Eloquent scopes use the orderBy
method – this is just syntactic sugar to make it easier to write and read.
How can you sort by multiple columns in Eloquent? Well, just use the orderBy
method twice!
Here's an example of ordering by multiple columns:
$posts = Post::orderBy('title', 'desc')
->orderBy('published_at', 'asc')
->get();
In this example, multi-column ordering works by first ordering by title
and then by published_at
if two titles exist with the same value. Pretty unlikely in the case of a blog post, but apply this to your own queries where it makes sense.
Because Eloquent relationships return a Builder
, we can directly order when we define these relationships.
class User extends Model
{
public function posts()
{
return $this->hasMany(Post::class)
->latest();
}
}
We're using the latest
scope here, but you can use any ordering technique directly chained onto the relationship to always order it when accessed.
You can clear previously ordered queries in Eloquent using the reorder
method. This is useful if you're always ordering a relationship in a certain way but need to undo it for a particular case.
Let's take the relationship we looked at in the last section:
class User extends Model
{
public function posts()
{
return $this->hasMany(Post::class)
->latest();
}
}
Any time we access posts from a user, they'll always be ordered by created_at
in desc
order.
To clear ordering wherever you need, use reorder
:
$posts = auth()->user()
->posts()
->reorder()
->oldest()
->get();
We've used reorder
to clear the previous order before using oldest
to perform the new order.
You can do this all in one hit by passing some arguments through to reorder
:
$posts = auth()->user()
->posts()
->reorder('created_at', 'asc')
->get();
This means you don't need to use orderBy
, oldest
or any other ordering functionality — reorder
will do it all in one go.
If you need to randomly order results with Eloquent, use the inRandomOrder
method:
$posts = Post::inRandomOrder()->get();
Behind the scenes, this will use an SQL RANDOM()
function to seed the query with a random order, perform a raw query, and return your results randomly ordered.
Just be aware that this will result in a slightly slower query, so it's best to cache your results for a short period if you can.
If you need to order with a raw query in Eloquent, you can use orderByRaw
:
$posts = Post::orderByRaw(`created_at DESC`)->get();
This example just orders in the same way latest
or orderBy
would, but you can pass any valid SQL in here.
We've already seen an example of ordering randomly, but here's how this would look with orderByRaw
:
$posts = Post::orderByRaw(`RANDOM()`)->get();
If you find yourself repeating a specific order throughout your application, creating a scope to deal with this helps tidy things up.
On your model, define a new scope:
class Post extends Model
{
public function scopeOrderByPublishedDate($query)
{
$query->orderBy('published_at', 'desc');
}
}
Any scopes you create should be prefixed by scope
, followed by the name of your scope.
Now you've defined a scope, use it like this:
$posts = Post::orderByPublishedDate()->get();
Now, rather than use orderBy('published_at', 'desc')
throughout your application, you can use a scope, which is much easier to type, read, and remember.