0

I need to fetch a type (to get the logged user's orders) by giving the current User to the scopeAvailableForUser.

So I did the following

extend type Query {
    wallet(
        user: User = me @scope(name: "availableToUser")
    ): [DigitalProduct!]  @all
}

but it doesn't work, it's returning

"errors": [
    {
        "message": "Unknown type: User.",
        "extensions": {
            "category": "graphql"
        }
    }
]

So, how can I provide the user to a scope directive ?

gizon_dev
  • 36
  • 1
  • 5

1 Answers1

1

You might use a relationship like belongsTo and nest it on the User type as a DigitalProduct that is linked to the user should have a relationship with a belongsTo and hasMany I would think.

extend type User {
  wallet: [DigitalProduct!]! @hasMany
}

If writing an API a public user and a private user that is returned for a query like me or currentUser is nice to have. Multiple types can point at the same model using @model(class: "App\Models\User")

So I have a PublicUser type I use in relationships and then for viewing authorized user (logged in user) records I use the real User type. This lets me secure it so that 1 user cannot see another users more "private" relationships/data.

There is also @inject which can be used to grab the user id from context.

Inject a value from the context object into the arguments. https://lighthouse-php.com/master/api-reference/directives.html#inject

Which you might use like this. Note: Inject would overwrite any user supplied value.

extend type Query {
  wallet(user_id: Int! @whereKey) @all @inject(context: "user.id", name: "user_id")

However this does not necessarily use the scope.

I'm trying to figure out how to put the variable from user.

The docs say

The scope method will receive the client-given value of the argument as the second parameter. https://lighthouse-php.com/master/api-reference/directives.html#scope

So if the scope had an argument of user_id maybe it would pass it accordingly in conjunction with inject?


In my use-case I want to pass user defined values through to the scope. Not the logged in user in this case as I use the relationships for that. But this question came up when I searched.

I'm using Spatie/Tags package.

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
// ...
    public function scopeWithType(Builder $query, string $type = null): Builder
    {
        if (is_null($type)) {
            return $query;
        }

        return $query->where('type', $type)->ordered();
    }

    public function scopeContaining(Builder $query, string $name, $locale = null): Builder
    {
        $locale = $locale ?? static::getLocale();

        return $query->whereRaw('lower(' . $this->getQuery()->getGrammar()->wrap('name->' . $locale) . ') like ?', ['%' . mb_strtolower($name) . '%']);
    }
// ...
}

So a schema like this works.

# noinspection GraphQLUnresolvedReference,GraphQLMissingType
union HasTags = Restaurant | Dish | Grub

type Tag @model(class: "Spatie\\Tags\\Tag") {
    id: ID!
    name: String!
    slug: String!
    type: String!
    order_column: Int!
    created_at: DateTime!
    updated_at: DateTime!
}

extend type Query {
    "Find a Tag by id."
    tag(id: ID! @eq): Tag! @find

    "Find a tag containing a given name for a given type."
    tags(name: String! @scope(name: "containing"), type: String! @scope(name: "withType"), limit: Int = 10 @limit): [Tag!]! @all @orderBy(column: "order_column")
}
Liam Mitchell
  • 1,001
  • 13
  • 23