ideas
ideas copied to clipboard
hasOneThrough on same table would add alias for join
Hello, I think the hasOneThrough relationship should be a bit smarter then it is right now, maybe this also applies for the hasManyThrough relationship but never looked at that one.
Idea:
I'm talking about when you set up a hasOneThrough
relationship on one table so the first table is the same as the second table you pass through, so maybe Laravel can maybe check if they are the same and if so add an alias for the join clause.
I think the example below will make it more clear.
Example:
So imagine that you have a page with subpages and they are both stored in the same table called pages
and you also have a comment that is stored in a table called comments
.
(!) Important to know is that a subpage can not have subpages.
So the tables will look something like this:
pages table:
id
parent_id
name
...
comments table:
id
page_id
message
votes_counter
...
And the models will have this relationships setup:
// Page model
public function parent()
{
return $this->hasOne(Page::class, 'parent_id');
}
// Comment model
public function page()
{
return $this->hasOne(Page::class);
}
Now you have two pages Questions about SMTP
and How to setup SMTP on Apple
and we have a comment that has over 100 upvotes that is connected to the How to setup SMTP on Apple
page.
Let's say that on the page where you want to show all comments that has a voting of 100 or more and want to show the parent of the subpage that the comment is connected to.
So the code in most cases would look something like this:
$comments = Comment::where('votes_counter', '>=', 100)->with('page.parent')->get();
// or
$comments = Comment::where('votes_counter', '>=', 100)->with('page.parent')->whereHas('page.parent')->get();
foreach($comments as $comment) {
echo $comment->page->parent->name;
}
So to show this you need three queries and in most systems that's fine, but if you have a lot of traffic it is not so handy.
Of course you also need to go through two relations to get the name you really wanted, but now you also loaded all the data of the subpage that the comment is connected to and you not even showing it somewhere.
// Query on the comments table
SELECT * FROM comments WHERE `votes_counter` >= 100
// Queries on the pages table
SELECT * FROM pages WHERE `id` IN(3, 4, 5)
// And the next to get the parent
SELECT * FROM pages WHERE `id` IN(1, 2) // 1 and 2 are the parent pages of 3, 4 and 5
So that's why I thought it would be great to use the hasOneThrough
relation to load the parent page and save fetching all the data I don't even need.
I understand you can also do this with a join clause yourself but it feels nicer to stick to the options the framework gives and it's maybe a bit better to read.
I will do my best to respond as soon as I can if you have any questions.
Same situation here.
+1 same situation here too. If I find a workaround I will post it, maybe someone else has already found a way?
Solved my use case by using accessors - https://laravel.com/docs/8.x/eloquent-mutators#accessors-and-mutators