Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[10.x] Allow for converting a HasMany to HasOne && MorphMany to MorphOne #46443

Merged

Conversation

cosmastech
Copy link
Contributor

@cosmastech cosmastech commented Mar 12, 2023

Problem

There are often times where I am building a HasMany relationship and I need to get just one item from the collection. This means I have to either define the relationship two times (one for HasMany and then one for HasOne->ofMany()).

class User extends Model
{
    public function logins(): HasMany {
        return $this->hasMany(Login::class, 'some_id', 'the_other_id');
    }
    public function latestLogin(): HasOne {
        return $this->hasOne(Login::class, 'some_id', 'the_other_id')->latestOfMany();
    }
}

As you can imagine, if the design of the DB changes (like during early development of a project) or if the relationship isn't simple, this can be cumbersome or lead to duplication of work.

Proposed Solution

What is added in this PR is the ability to convert a HasMany relationship to HasOne (and MorphMany to MorphOne). So the above code can become

class User extends Model
{
    public function logins(): HasMany {
        return $this->hasMany(Login::class, 'some_id', 'the_other_id');
    }
    public function latestLogin(): HasOne {
        return $this->logins()->hasOne()->latestOfMany();
    }
}

@cosmastech cosmastech force-pushed the feature/morph-one-and-has-one-from-many branch from d46f0a2 to 91283d8 Compare March 13, 2023 09:25
@cosmastech
Copy link
Contributor Author

If this is something that makes sense, will gladly add HasManyThrough@hasOneThrough() method as well

@cosmastech cosmastech force-pushed the feature/morph-one-and-has-one-from-many branch from 91283d8 to 1a871f8 Compare March 13, 2023 11:01
@cosmastech cosmastech changed the title Allow for converting a HasMany to HasOne && MorphMany to MorphOne [10.x] Allow for converting a HasMany to HasOne && MorphMany to MorphOne Mar 13, 2023
@taylorotwell taylorotwell merged commit 38f022d into laravel:10.x Mar 13, 2023
@taylorotwell
Copy link
Member

Thanks

@siarheipashkevich
Copy link
Contributor

siarheipashkevich commented Mar 24, 2023

@cosmastech could you please check which sql query will be generated? I saw that the sql query has duplicated conditions...

@cosmastech
Copy link
Contributor Author

cosmastech commented Mar 24, 2023

@cosmastech could you please check which sql query will be generated? I saw that the sql query has duplicated conditions...

@siarheipashkevich could you provide a code sample the generated SQL?

edit: I see now.

$user->userPreferences()->one()->toSql();
// select * from `user_preferences` where `user_preferences`.`user_id` = ? and `user_preferences`.`user_id` is not null and `user_preferences`.`user_id` = ? and `user_preferences`.`user_id` is not null

@siarheipashkevich
Copy link
Contributor

I've terminal model with next relations:
image

In Shift model I've opened scope:
image

Get openedShift from terminal:
image

Logs:

[2023-03-24 11:41:38] local.INFO: select * from `shifts` where `shifts`.`terminal_id` = ? and `shifts`.`terminal_id` is not null and `shifts`.`terminal_id` = ? and `shifts`.`terminal_id` is not null and `closed_at` is null and `shifts`.`deleted_at` is null limit 1 [480,480] 
[2023-03-24 11:41:38] local.INFO: see logs above  

@siarheipashkevich
Copy link
Contributor

siarheipashkevich commented Mar 24, 2023

@cosmastech could you please check which sql query will be generated? I saw that the sql query has duplicated conditions...

@siarheipashkevich could you provide a code sample the generated SQL?

edit: I see now.

$user->userPreferences()->one()->toSql();
// select * from `user_preferences` where `user_preferences`.`user_id` = ? and `user_preferences`.`user_id` is not null and `user_preferences`.`user_id` = ? and `user_preferences`.`user_id` is not null

Please take a look at your sql. You also have diplicated conditions

`user_preferences`.`user_id` = ? and `user_preferences`.`user_id` is not null and `user_preferences`.`user_id` = ? and `user_preferences`.`user_id` is not null

@cosmastech
Copy link
Contributor Author

@siarheipashkevich thank you for reporting this! #46575 should resolve this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants