Lighthouse: Only the last scopes are called

Created on 30 Aug 2018  路  5Comments  路  Source: nuwave/lighthouse

Describe the bug
When you have multiple scopes in the query with @paginate directive only the last
scopes are called.

Expected behavior
When I var_dump in PaginateDirective

protected function paginatorTypeResolver(FieldValue $value, $model)
    {
        return $value->setResolver(function ($root, array $args) use ($model) {
            $first = data_get($args, 'count', 15);
            $page = data_get($args, 'page', 1);

            var_dump($this->directiveArgValue('scopes', []));
            die();

            $query = QueryUtils::applyFilters($model::query(), $args);
            $query = QueryUtils::applyScopes($query, $args, $this->directiveArgValue('scopes', []));

            Paginator::currentPageResolver(function () use ($page) {
                return $page;
            });

            return $query->paginate($first);
        });
    }

It returns array(2) {\n [0]=>\n string(12) \"filterBySite\"\n [1]=>\n string(13) \"orderByLatest\"\n}\n

Which should be

array(2) {\n [0]=>\n string(12) \"filterBySite\"\n [1]=>\n string(13) \"orderByOldest\"\n}\n

Schema

oldestPosts(count: Int!, page: Int): [Post!]!
        @paginate(
            model: "Post"
            scopes: ["filterBySite", "orderByOldest"]
        )

    latestPosts(count: Int!, page: Int): [Post!]!
        @paginate(
            model: "Post"
            scopes: ["filterBySite", "orderByLatest"]
        )

I'm calling oldestPosts but I get array(2) {\n [0]=>\n string(12) \"filterBySite\"\n [1]=>\n string(13) \"orderByLatest\"\n}\n.

latestPosts(count: Int!, page: Int): [Post!]!
        @paginate(
            model: "Post"
            scopes: ["filterBySite", "orderByLatest"]
        )

    oldestPosts(count: Int!, page: Int): [Post!]!
        @paginate(
            model: "Post"
            scopes: ["filterBySite", "orderByOldest"]
        )

Now I get array(2) {\n [0]=>\n string(12) \"filterBySite\"\n [1]=>\n string(13) \"orderByOldest\"\n}\n when calling oldestPosts. But now I try the latestPosts & I get the oldestPosts scopes. So the last scopes are the one that have priority it seems.

Environment

Lighthouse Version: 2.1.1
Laravel Version: 5.6.33
PHP Version: 5.7

Additional context
Is this the way you intended to be? Only being able to work with one scopes param.

UPDATE: Workaround for my use case

This isn't a full workaround because if you have the same name it still looks for only the first one. I have limited time to look into this so this is the first thing that came to mind. Hope it helps somebody :)

protected function paginatorTypeResolver(FieldValue $value, $model)
    {
        return $value->setResolver(function ($root, array $args) use ($model) {
            $first = data_get($args, 'count', 15);
            $page = data_get($args, 'page', 1);

            $customScopesName = lcfirst(str_replace('App\\', '', $model) . 'Scopes');

            $query = QueryUtils::applyFilters($model::query(), $args);
            $query = QueryUtils::applyScopes($query, $args, $this->directiveArgValue($customScopesName, []));

            Paginator::currentPageResolver(function () use ($page) {
                return $page;
            });

            return $query->paginate($first);
        });
    }

Just take the scopes word & make it unique by adding the model onto it since the model is required anyway. This seems to work because directiveArgValue only looks for the first name that equals scopes it comes to. Also this only works if you use App\ for namespace. If you don't use App\ just change it to your namespace.

$arg = collect($directive->arguments)->first(function (ArgumentNode $argumentNode) use ($name) {
            return $argumentNode->name->value === $name;
        });

This is the code that only looks for the first "scopes" or other names as well.

FYI: I made a custom directive for this. I would not recommend editing the main composer files.

bug

All 5 comments

@dragonfire1119 I believe this may be taken care of in v2.2 of the package. Previously the same instance of the directive class was being used to process each field. In v2.2 a new directive instance is used for each field and I think that should resolve the issue you're experiencing. Could you give it a try and let us know if you're still running into this problem? Thanks for reporting!!

@chrissm79 Thanks for the response back. I had this problem with every directive & the only workaround for those problems where to use the @field directive and resolve the query or mutation from it's own class. I didn't have my problem until the project began to grow allot & needed more & more .graphql files extending. I will try the v2.2 on a test branch soon. I was wondering why the @field is the only reliable directive in v2.1.*. I haven't had allot of time to look into it though. Thanks for lighthouse!

@chrissm79 Wow it worked! Great job! No more mix ups with scopes so far knock on wood! LOL I'm going to do some more testing but it looks like 2.2 fixed it. Ill report back when I'm done with testing 2.2 on another project.

@chrissm79 All my tests worked so far! Thanks for the quick update to 2.2.

Glad it resolved your issue @dragonfire1119!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mikeerickson picture mikeerickson  路  3Comments

nguyentrongbang picture nguyentrongbang  路  3Comments

alexwhb picture alexwhb  路  4Comments

spawnia picture spawnia  路  4Comments

a-ssassi-n picture a-ssassi-n  路  3Comments