3

I'm creating a GraphQL implementation of an existing API. I'm using Laravel 5.8 with Lighthouse 3.7.

I'm wondering how to implement a search functionality using this - something along the lines of...

scheme.graphql

type Query {
    userSearch(name: String, email: String, phone: String, city_id: Int): [User] #Custom Resolver - app/GraphQL/Queries/UserSearch.php
}
type User {
    id: ID!
    name: String!
    email: String
    phone: String
    credit: Int
    city_id: Int
    city: City @belongsTo
}

UserSearch.php

public function resolve($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
{
    $q = app('db')->table('users');
    foreach($args as $key => $value) {
        $q->where($key, $value);
    }
    $users = $q->get();

    return $users;
}

This would work - but only for the fields that are returned by the query.

{
    userSearch(name:"Picard") {
        id          # This will work
        name        # This will work
        city {      # These wont.
            id      # These won't work
            name    # These won't work
        }
    }
}

I'll get this error when I try it...

"debugMessage": "Argument 1 passed to Nuwave\\Lighthouse\\Schema\\Directives\\RelationDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}() must be an instance of Illuminate\\Database\\Eloquent\\Model, instance of stdClass given, called in /mnt/x/Data/www/Projects/Phoenix/vendor/nuwave/lighthouse/src/Schema/Factories/FieldFactory.php on line 221"

I know what is going wrong - the $users in the resolve function is returning a interatable object - and not a model - like hasMany or belongsTo returns. I'm wondering what is the right way to do this.

Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183
Binny V A
  • 2,036
  • 3
  • 20
  • 23
  • you probably need some `->join('cities')` (left?) in resolver – xadm Jun 22 '19 at 19:40
  • What you are trying to do should be possible to do without using a custom resolver. Just use the `eq` directive on your arguments instead https://lighthouse-php.com/3.7/api-reference/directives.html#eq – Oliver Nybroe Jun 25 '19 at 21:24

2 Answers2

2

What you are trying to do should be possible without using a custom resolver.

You should be able to do it with something in the likes of the following

type Query {
    userSearch(name: String @eq, email: String @eq, phone: String @eq, city_id: Int @eq): [User] @paginate
}
type User {
    id: ID!
    name: String!
    email: String
    phone: String
    credit: Int
    city_id: Int
    city: City @belongsTo
}

Here we utilize the paginate method and extending it with some constraints.

Oliver Nybroe
  • 1,828
  • 22
  • 30
  • This is helpful - but not exactly what I'm looking for. I want to add some filters in the resolver before returning the data(things like status = 1 and a few others). – Binny V A Jun 26 '19 at 11:56
  • You can do that by using the scope directive and then add the scope to your user model. Else if you could show a complete example of what you actually want, then I'll try and help with that. – Oliver Nybroe Jun 26 '19 at 12:14
1

The best way that I've tried throughout my project is to add a public static scopeSearch function in the User model and perform search there, and then easily use the code below to do the search:

users(q: String @search): [User]
@paginate(model: "App\\Models\\User")

The @search will trigger the search function in your model.

Alireza A2F
  • 519
  • 4
  • 26