Reputation: 1649
I have one parent model with a child relationship that I'm trying to order by another relationship with the child.
Plan
-- Items
--- Details
Plan to items is one to many relationship. Items to Details is one to one relationship. I want the Items to be ordered by a field that's set in the details like a title for example. I was thinking that it would look something like in this article.
Plan::with([
'items.details' => function ($query) {
$query->orderBy('title', 'asc');
}])
->findOrFail(1);
It doesn't work. I have seen a lot of ways on how to add it to the Parent (Plan) model, but I want to order a relationship--not the parent especially since it's only 1 Plan. I'm sure there is a simple solution, but I can't wrap my mind around it.
Upvotes: 1
Views: 1069
Reputation: 1649
I don't know if anyone else will run into this issue. The answer that TsailKoga did work, but the collection were interesting. Like the relationships got pushed to parent. For example.
Plan (parent)
-- Items
--- Details
All the Details attributes became part of the items. It worked but wasn't quite the result I wanted. I tried doing some funky usort
, but once you convert a collection to an array to use with usort, you lose all of the tools that goes along with collections/eloquent. I found a way that didn't require anything fancy. Collections have a sortBy
method. All I had to do is something like $plan->items->sortBy('details.title')
and viola. Plan Items were sorted by title. Days of work for 1 line of code.
I hope this helps someone else out.
Upvotes: 0
Reputation: 13394
Since the title
is from another table details
, the items
and the details
's relationship is one-to-one, you can use leftjoin
like this:
Plan::with([
'items' => function ($query) {
$query->leftjoin('details', 'details.item_id', '=', 'items.id')
->select('items.*', 'details.title')
->orderBy('title', 'asc');
}])
->findOrFail(1);
Upvotes: 2