cms icon indicating copy to clipboard operation
cms copied to clipboard

[5.x] Add support for `whereHas()` and `whereRelation()` to entry and user query builders

Open ryanmitchell opened this issue 1 year ago • 14 comments

This PR adds support for queries on 'relationship' fields in the format:

$entries = Entry::query()->whereHas('entries_field', function ($subquery) {
   $subquery->where('title', 'Post 2');
});

$entries = Entry::query()->whereHas('entries_field');

$entries = Entry::query()->whereRelation('entries_field', 'title', 'Post 2');

I've added support to both Entry and User query builders, but as it can be easily added to other query builders if required - each query builder just needs to provide the appropriate blueprints through the getBlueprintsForRelations method.

The logic going on behind the scenes is to loop over the blueprint(s) and get the first relationship field type that has the same handle as the relation name being asked for. We then use the appropriate Facade to do another query to match the ids we want, and then do a check on the relationship field for those ids, this is provided by a new relationshipQueryBuilder() method on the fieldtype (currently only applied to entries and user fields, this would need to be extended).

It doesn't currently support checking counts on where callbacks (ie in the format):

Entry::query()->whereHas('entries_field', function ($query) {
    $query->where('content', 'like', 'code%');
}, '>=', 10)

And an InvalidArgumentException is thrown if this is attempted.

Looking forward to hearing your thoughts on this.

ryanmitchell avatar Jul 21 '23 06:07 ryanmitchell

Awesome 🎉

jasonvarga avatar Jul 24 '23 19:07 jasonvarga

@jasonvarga when are you guys planning to release, need this badly

saqueib avatar Sep 04 '23 05:09 saqueib

The Statamic Team will review this when they can.

In the meantime, you can use a composer patch to bring this PR into your project.

duncanmcclean avatar Sep 04 '23 06:09 duncanmcclean

@jasonvarga Any update on this pull request. I'm missing this issue right now in two projects. @duncanmcclean I've tried your method but I can't get it to work. It is stuck applying the patch. Also tried the beta version of the package without success.

justkidding96 avatar Sep 25 '23 15:09 justkidding96

@justkidding96 if you remove the tests from the patch file it should install without issues.

robdekort avatar Sep 25 '23 15:09 robdekort

Is there a possibility that a collection tag parameter could be added for easy filtering (ie. without creating a scope)

godismyjudge95 avatar Oct 04 '23 18:10 godismyjudge95

@jasonvarga Any update on this pull request. I'm missing this issue right now in two projects. @duncanmcclean I've tried your method but I can't get it to work. It is stuck applying the patch. Also tried the beta version of the package without success.

I had the same issue; setting preferred-install (under config in composer.json) to source fixed it for me.

godismyjudge95 avatar Oct 04 '23 20:10 godismyjudge95

Apologies for the spam on this, I'm just really invested in this feature 😂

Would love to see Taxonomy/Terms included in this feature. Here's the relevant code:

    // src/Stache/Query/TermQueryBuilder.php

    protected function getBlueprintsForRelations()
    {
        $wheres = collect($this->wheres);

        $taxonomies = $wheres->where('column', 'taxonomy')
            ->flatMap(function ($where) {
                return $where['values'] ?? [$where['value']] ?? [];
            })
            ->unique();

        if (!$taxonomies->count()) {
            $taxonomies = Facades\Taxonomy::all();
        }

        return $taxonomies->flatMap(function ($taxonomy) {
            if (is_string($taxonomy)) {
                $taxonomy = Facades\Taxonomy::find($taxonomy);
            }

            return $taxonomy ? $taxonomy->termBlueprints() : false;
        })
            ->filter()
            ->unique();
    }

godismyjudge95 avatar Oct 05 '23 05:10 godismyjudge95

@godismyjudge95 yes it needs extended to a number of other field types, one of which is Taxonomies. My intention had been for the initial approach to be approved and merged after which I would raise separate PRs for the other field types to gradually get to complete support.

ryanmitchell avatar Oct 05 '23 06:10 ryanmitchell

I had the same issue; setting preferred-install (under config in composer.json) to source fixed it for me.

Oh my this is brilliant. I don't know if there's any security downsides to this. But using this we can easily patch in PR's with tests via a GH link without manually downloading the patch file and removing the tests. Thanks.

robdekort avatar Oct 05 '23 08:10 robdekort

This PR works very well. Thanks @ryanmitchell.

robdekort avatar Oct 05 '23 08:10 robdekort

Just wanted to follow up on this and say the taxonomy and collection changes are working great for me. I've run into no other issues.

godismyjudge95 avatar Oct 31 '23 17:10 godismyjudge95

If possible could you update this PR to the latest version? We are using it via composer patches. Thanks! :)

godismyjudge95 avatar Dec 11 '23 23:12 godismyjudge95

If you get a chance could you update this for the latest Statamic version? (for composer patches) Thanks :)

godismyjudge95 avatar Jan 10 '24 17:01 godismyjudge95