-
Notifications
You must be signed in to change notification settings - Fork 28
joinRelation #668
Comments
@browner12 @sileence any thoughts guys? Looks like people are interested in this feature. |
i was actually just thinking about this yesterday as I was looking into some query optimization stuff. I would love to utilize Join queries in our relationships, to decrease the number of queries we actually make. Let's take an example. A $city = City::first(); and then try to output it's full name echo $city->name . ', ' . $city->state->name . ' ' . $city->state->country->name; We end up making a query for each relationship. It would be great if these SELECT *
FROM cities as c
JOIN states as s
ON c.state_id = s.id
JOIN country as co
ON s.country_id = co.id and then auto-populate these into related models on the base class. I'm not sure that I have the bandwidth for this right now given my workload but I will continue to look into it. |
Also we will can sort models by relationship field. |
This would need both automatic aliasing of the columns to avoid conflicts between models that have identical column names (like Your examples so far has been many-to-one/belongs-to relations. What about the original question, a one-to-many/has-many? This would need for a hydrator that understands that several rows returned does not mean that several root entities should be returned. Assuming the original imagined code;
I would expect the query to return two User models, where the posts relation is eager loaded. User 1 (sisve) should have a Collection with two Posts, User 2 (lurker) should have an empty Collection since he has never written anything. |
Hello, there are a few things to consider here:
With that information it will be possible to hydrate the models if we cycle through the relationships and we process them similar to what I've been working on here: laravel/framework#19793 BUT the problem is that the current version of Eloquent does not specify the column names, and therefore there is no way to build the SELECT part of the query unless we get the column names from the database (and we cache them somewhere). I hope this helps. |
@sileence Of course this proposal is not about optimisation but about Laravel users convenience. Initially I just want wrapper around Later I saw existing solutions grouped rows by parent model and I think it will be superflexible if we can control both situations. |
@sisve I'm not sure if this is in the pipeline for next Laravel release, but I'd like to see the default What I think makes sense is that only the model's fields should be selected - if you need to retrieve data from the joined tables, either use The current behaviour is IMHO both confusing and dangerous - leading to things like identifiers being overwritten. Of course, if the relationship is one to many, multiple model instances will be created - however, that's up to the dev to know their data structure. I'd be happy to raise this as another issue, if this isn't in the pipeline. |
The proper api for filtering is We wouldn't need to worry about identifiers being overwritten if we're automatically aliasing all model attributes. |
+1 |
I really want this feature! |
@Inkognitoo Could you tell us which specific feature you want, and how yii2 implemented that feature? Everything I find under http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#joining-with-relations matches what Laravel already supports. I see nothing in their docs about any support for populating relationships via joins, or automatic aliasing of columns. Maybe you're just easily upset? |
CakePHP2 supports this too and, yes I'm guilty, I found it useful when I needed it. More information can be found here: https://book.cakephp.org/2.0/en/models/retrieving-your-data.html When using its ORM, it always aliases the columns you retrieve and thus when it combines them with other queries, there won't be a clash. But you can run into other problems, like the column name aliases being to long and getting cut off (Problem with postgres). The thing is:
The outcome for me was fine enough not pursuing any kind of solution do that. |
@sisve I'm not sure I understand you right, but... For example: I need to sort table by sum of aggregate row another table. In Yii2 if I want alias for join table, I write something as $query->joinWith('books b') it create b alias for books table. |
@Inkognitoo - one of my real world examples was similar... I wanted to order the results of a collection by a value in a joined table, so has() or whereHas() aren't helpful here. |
Hi Guys I wrote a gist with an useful Trait about query join through relations https://gist.github.com/MatteoOreficeIT/d3f66e90436dd5b9c90fbe144118e667 Example public function scopeJoinWith(Builder $builder,$relationSegments,$rightAlias=null,$operator='=',$join='join')
// some usage examples
\App\Terminali::query()->select('S.*')->joinWith('settori','S');
\App\Terminali::query()->select('P.*')->joinWith(['settori','prodotto'],'P');
\App\Terminali::query()->select('P.*','S.*')->joinWith(['settori','prodotto'],['P','S']);
\App\Terminali::query()->from(\App\User::query()->getModel()->getTable().' as U')->select('U.*','S.*')->joinWith(['settori','prodotto'],['P','S']); It works on BelongsTo and HasOneOrMany I hope it could be integrated in the future |
What was the reason for closing this? Is it implemented somewhere? |
@jpleau no |
Too bad. This would have been really useful. |
I created a package that solves above problems : https://github.com/fico7489/laravel-eloquent-join |
As we know Eloquent uses separate query for relationships but sometimes we need JOIN relationship (for sorting by relationship column or for aggregate functions like
sum
,count
etc.)Then we have to use
join
method onBuilder
and we need to specify joining columns with hardcoded names:User::join("posts", "user.id", "=", "posts.user_id")
It would be cool to have method
joinRelation
which could determine needed parameters automatically from relation definition:.For example:
and then (just an example):
without need for check column names.
Just ping @browner12 and @sileence in case they are interested in this and could implement this.
The text was updated successfully, but these errors were encountered: