Reputation: 646
I recently wanted to sort parent elements of a collection by using their relationship values so I came across something like this and It works. Do you think this is a suitable method or am I making this overcomplicated?
Basically, I want to sort the Events by their date
Events have one to many with Slots
Any review on this would be appreciated
Cheers
$events = Event::with(['slots' => function ($q) {
$q->orderBy('date');
$q->orderBy('start_time');
}])->active()->get();
$slotArray = [];
foreach($events as $event){
foreach ($event->slots as $slot) {
$slotArray[$slot->id] = [ 'id' => $event->id, 'start_date' => $slot->date, 'start_time' => $slot->start_time];
}
}
//Sort the Array of IDS
usort($slotArray, array($this,"sortByStartDate"));
//Find the New Set of IDS sorted by the Start Date
$sortedEventIDs = [];
foreach($slotArray as $value) {
array_push($sortedEventIDs, $value['id']);
}
$sortedEvents = $events->sortBy(function($model) use ($sortedEventIDs){
return array_search($model->getKey(), $sortedEventIDs);
});
Sort Function
function sortByStartDate($a, $b){
return $a['start_date'] > $b['start_date'];
}
Upvotes: 0
Views: 353
Reputation: 18916
There is an SQL approach, that would look something like this. Create an subselect, fetch the date you want to use and order by it.
Event::with(['slots' => function ($q) {
$q->orderBy('date');
$q->orderBy('start_time');
}])
->addSelect([
'date' => Comment::selectRaw('MAX(start_date)')
->whereColumn('events.id', 'comments.event_id'),
])->orderBy('date');
Simply use Laravel relation and do the same, not as performance optimized but very straight forward aproeach.
$events = Event::with(['slots' => function ($q) {
$q->orderBy('date');
$q->orderBy('start_time');
}])->active()->get();
$events->sortBy(function ($event) {
return $event->slots()->max('start_date');
});
Upvotes: 2
Reputation: 1864
You can use orderBy() function:
$events = Event::orderBy('start_time', 'DESC')->active()->get();
and for the IDs, you can use sortKeys():
$sorted = $events->sortKeys();
$sorted->all();
Upvotes: 0