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

whereHas with nested relation is broken #24407

Closed
afraca opened this issue Jun 1, 2018 · 10 comments
Closed

whereHas with nested relation is broken #24407

afraca opened this issue Jun 1, 2018 · 10 comments

Comments

@afraca
Copy link
Contributor

afraca commented Jun 1, 2018

  • Laravel Version: 5.5.x
  • PHP Version: 7.0.30
  • Database Driver & Version: mysql

Description:

When working with relations, there is the whereHas method, constraining things on a relation, described here:
https://laravel.com/docs/5.5/eloquent-relationships#querying-relationship-existence
There should be support for nested relations, but this will fail with an 'undefined function on Builder'. I looked into this.

Steps To Reproduce:

Model A belongsTo B
Model B belongsToMany C

When doing
A::with('b.c')->whereHas('b.c', function($q){})->get();
we see failure of the 'undefined function c'.


I looked into this and saw in the QueriesRelationship trait multiple calls to getRelationWithoutConstraints. There we have $this->getModel() and in the reproduction case we see that returning A and A, not A and B. I think that's part of the problem.
Sorry I can't provide a reproducing repo here on Github, no time today.

@afraca
Copy link
Contributor Author

afraca commented Jun 1, 2018

ps: I think why no tests have caught this is because the tests only test with a self-referencing relation! See:

$results = EloquentTestPost::whereHas('childPosts.childPosts', function ($query) {

@staudenmeir
Copy link
Contributor

staudenmeir commented Jun 1, 2018

It works for me on 5.5 and 5.6. Can you post the models?

@afraca
Copy link
Contributor Author

afraca commented Jun 2, 2018

Set up a clean laravel project and got a reproducable case, will put code on github in a moment.
I'm using polymorphic relations though, perhaps that could be related, not sure at the moment.

@afraca
Copy link
Contributor Author

afraca commented Jun 2, 2018

Here it is:
https://github.com/afraca/laravel-issue24407

The Spatie Medialibrary lets you tie files to anything. If you however want to use one file on multiple items in your application, you have to use some middle model, the FileAssociator in my reproducing repo.
This FileAssociator can then be tied to multiple items (polymorphic many to many).

Now, if you want to select files which only have a page with status '1', you use the code from web.php , the home route, this code for retrieval:
dump(File::whereHas('model.pages', function (Builder $builder) { $builder->where('status', '1'); })->all());

That fails, with: Call to undefined method Illuminate\Database\Query\Builder::pages()

@staudenmeir
Copy link
Contributor

whereHas() doesn't work with polymorphic relationships: #5429, #18523

@afraca
Copy link
Contributor Author

afraca commented Jun 2, 2018

While certainly interesting, it seems some parts DO work, and this counts as a separate, possibly fixable, issue.
We saw it working when we did things with the FileAssociator (see repo) directly. See this:

dump(FileAssociator::whereHas('pages', function(Builder $builder){
        $builder->where('status', '1');
    })->get()->count() === 1);

https://github.com/afraca/laravel-issue24407/blob/57302807c862843a36e86bb4b4ca49ec48ae38a3/routes/web.php#L35-L37

Produces (I think the expected) query:

"select * from `file_associators` where exists (select * from `pages` inner join `fileables` on `pages`.`id` = `fileables`.`fileable_id` where `file_associators`.`id` = `fileables`.`file_associator_id` and `fileables`.`fileable_type` = ? and `status` = ?)

@staudenmeir
Copy link
Contributor

staudenmeir commented Jun 2, 2018

To be more specific: MorphTo relationships don't work with whereHas().

As described in the linked issues, you would have to query multiple tables.

@afraca
Copy link
Contributor Author

afraca commented Jun 3, 2018

@tillkruss , can you clarify? This is not a duplicate. @staudenmeir was talking about MorphTo, but we're going the other way if I recall correctly. It almost works!

@tillkruss tillkruss reopened this Jun 3, 2018
@staudenmeir
Copy link
Contributor

You wrote that File::whereHas('model.pages' isn't working. model is a MorphTo relationship.

@afraca
Copy link
Contributor Author

afraca commented Jun 4, 2018

You're right, sorry, I got "obsessed" by the the fact the builder was doing multiple things on the File model, and I saw the FileAssociator example working. I'll close this as a duplicate of the issues you mentioned.

@afraca afraca closed this as completed Jun 4, 2018
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

No branches or pull requests

3 participants