Reputation: 1684
I've got a collection of records retrieved via a relationship, and I'd like to order them by the created_at
field. Is this possible in Eloquent?
Here is how I am retrieving the collection:
$skills = $employee->skills;
I'd like to order this $skills
collection by their creation. I've tried $skills->orderBy('created_at', 'desc');
but the Collection class does not have an orderBy
method.
I guess this problem is very simple and I'm missing something..
Upvotes: 1
Views: 2243
Reputation: 702
This Stackoverflow question askes how to order an Eloquent collection. However, I would like to propose a different solution to use instead given the example in the question. I would like to recommend to use an ordering on the query itself for performance reasons.
Like @Don't Panic proposes you can specify a default ordering on the relationship for great reusability convenience:
app/Models/Employee.php
public function skills() {
return $this->hasMany(Skills::class)->orderBy('created_at');
}
However, if you have already set an ordering on your query like we do in the code above, any additional orderings will be ignored. So that is a bummer if you want to use a different sorting in another situation. To overwrite this default ordering and re-order the query with a new ordering, one needs to use the reorder()
method. For example:
// Get a Collections of Skill-models ordered by the oldest skill first.
$skills = $employee->skills()->reorder()->orderByDesc('created_at')->get();
// Same result as the previous example, but different syntax.
$skills = $employee->skills()->reorder()->oldest()->get();
// Or just give some arguments to the reorder() method directly:
$skills = $employee->skills()->reorder('created_at', 'desc')->get();
Upvotes: 1
Reputation: 1103
You can do this in two ways. Either you can orderBy
your results while query, as in
$employee->skills()->orderBy('created_at', 'desc')->get();
OR
You can use sortBy
and sortByDesc
on your collection
Upvotes: 4
Reputation: 11906
Collection has sortBy
and sortByDesc
$skills = $skills->sortBy('created_at');
$skills = $skills->sortByDesc('created_at');
Upvotes: 0
Reputation: 14520
If you want the results to always be ordered by a field, you can specify that on the relationship:
Employee.php
public function skills() {
return $this->hasMany(Skills::class)->orderBy('created_at');
}
If you just want to order them sometimes, you can use orderBy()
, but on the relationship, not the property:
$skills = $employee->skills()->orderBy('created_at')->get();
Upvotes: 0
Reputation: 416
The reason this is failing is that orderBy
is a query method not a collection method.
If you used $skills = $employee->skills()->orderBy('created_at', 'desc')->get();
, this would query the skills in the order you want.
Alternatively, if you already had a collection that you wanted to re-order, you could use the sortBy
or sortByDesc
methods.
Upvotes: 1
Reputation: 8750
You need to add the orderBy
constraint on the query instead of the relationship.
For e.g,
$employees = Employee::where('salary', '>', '50000') // just an example
->with('skills') // eager loading the relationship
->orderBy('created_at', 'desc')
->get();
and then:
foreach($employees as $employee)
{
var_dump($employee->skill);
}
Upvotes: 0