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

[8.x] Add Eloquent builder whereMorphedTo method to streamline finding models morphed to another model #38668

Merged
merged 2 commits into from
Sep 7, 2021

Conversation

tobyzerner
Copy link
Contributor

@tobyzerner tobyzerner commented Sep 4, 2021

This PR adds whereMorphedTo and orWhereMorphedTo methods to the Eloquent Builder.

These methods are a shortcut for adding a where condition looking for models that are morphed to a specific related model, without the overhead of a whereHas subquery.

As an example, consider the following model:

class Feedback extends Model 
{
    public function subject() 
    {
        return $this->morphTo();
    }
}

Say we want to find feedback which is about a specific $model. One way to do this is to use whereHas:

$feedback = Feedback::whereHas('subject', [$model->getMorphClass()], function ($query) use ($model) {
    $query->where('id', $model);
})->get();

However, this is verbose and adds an unnecessary subquery. The information we want to constrain against is already in the feedback table. So, a more performant way would be to do this:

$feedback = Feedback::query()
    ->where('subject_type', $model->getMorphClass())
    ->where('subject_id', $model->getKey())
    ->get();

This is better, but it's still rather verbose. Also, the subject_type and subject_id columns are hard-coded – it would be better if we didn't have to worry about them and could automatically use the column names defined on the MorphTo relationship itself.

With this PR, the above can be replaced by this:

$feedback = Feedback::whereMorphedTo('subject', $model)->get();

It adds the same where clause, but is much simpler to read/write, and uses the column names defined on the MorphTo relationship.

@taylorotwell
Copy link
Member

I think it may be useful to be able to pass a string as the model name as well? ->whereMorphedTo('subject', Feedback::class);

@tobyzerner
Copy link
Contributor Author

tobyzerner commented Sep 6, 2021

Done. Not sure why the tests are failing in that particular instance, but it doesn't seem to have to do with the PR.

@GrahamCampbell GrahamCampbell reopened this Sep 6, 2021
@taylorotwell taylorotwell merged commit b3811be into laravel:8.x Sep 7, 2021
@tobyzerner tobyzerner deleted the where-morphed-to branch September 8, 2021 02:51
victorvilella pushed a commit to cdsistemas/framework that referenced this pull request Oct 12, 2021
…ing models morphed to another model (laravel#38668)

* Add Eloquent builder `whereMorphedTo` method to streamline finding models morphed to another model

* Add ability to pass string as the model name

return $this->where(function ($query) use ($relation, $model) {
$query->where($relation->getMorphType(), $model->getMorphClass())
->where($relation->getForeignKeyName(), $model->getKey());
Copy link
Member

@GrahamCampbell GrahamCampbell Mar 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this wrong if the relation uses something other than the model key as the owner key? $model->getKey() should be $relation->getRelatedKeyFrom($model)?

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