Giter VIP home page Giter VIP logo

Comments (4)

chrissm79 avatar chrissm79 commented on July 19, 2024

Hey @hailwood, great question!

graphql-php (which is what this package is built on) has a listOf type that can be used when you just want to return a list of types. A connection is better suited for when you want to do some pagination.

So if you wanted to have a list of users at the top level of your query you would just need to create a query which has a return type of a list of users like so:

Notice that the return type is wrapped in Type::listOf

use GraphQL;
use App\Models\User;
use GraphQL\Type\Definition\Type;
use Nuwave\Lighthouse\Support\Definition\GraphQLQuery;

class UsersQuery extends GraphQLQuery
{
    /**
     * Type query returns.
     *
     * @return Type
     */
    public function type()
    {
        return Type::listOf(GraphQL::type('user'));
    }

    /**
     * Available query arguments.
     *
     * @return array
     */
    public function args()
    {
        // ...
    }

    /**
     * Resolve the query.
     *
     * @param  mixed  $root
     * @param  array  $args
     * @return mixed
     */
    public function resolve($root, array $args)
    {
        return User::all();
    }
}

If you had users and wanted to return a list of tasks as a field with arguments you could do this:

use GraphQL;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\EnumType;
use Nuwave\Lighthouse\Support\Definition\GraphQLType;
use Nuwave\Lighthouse\Support\Interfaces\RelayType;
use App\Models\User;

class UserType extends GraphQLType implements RelayType
{
    // ...

    /**
     * Available fields of Type.
     *
     * @return  array
     */
    public function fields()
    {
        return [
            // ...
            'tasks' => [
                'args' => [
                    'status' => [
                        'type' => new EnumType([
                            'name' => 'UserStatus',
                            'values' => [
                                'OPEN' => ['value' => 1],
                                'CLOSED' => ['value' => 0]
                            ],
                        ])
                    ],
                ],
                'type' => Type::listOf(GraphQL::type('task')),
                'resolve' => function (User $user, array $args) {
                    $tasks = $user->tasks();

                    if ($status = array_get($args, 'status')) {
                        $tasks->where('status', $status);
                    }

                    return $tasks->get();
                }
            ],
        ];
    }
}

Hope that helps, but let me know if you still have questions!

from lighthouse.

hailwood avatar hailwood commented on July 19, 2024

Aha! Thanks @chrissm79,

I was missing,

return Type::listOf(...);

I was trying

return GraphQL::listOf(GraphQL::type('user'));

which obviously doesn't work 👍 .

One last part of is how would we paginate these (I'm mostly interested in a relay style approach, but both relay and non-relay would probably be useful for others).

Also, is there any way we can contribute to the documentation?
I wouldn't mind writing up some docs on these things.
I had contemplated starting some pages on the wiki, but I don't want to split the docs over two areas.

Cheers,
Matt

from lighthouse.

hailwood avatar hailwood commented on July 19, 2024

Alrighty, so after running through learnrelay.org I've managed to answer my own question. tl;dr You don't. That's not how relay works :)

from lighthouse.

chrissm79 avatar chrissm79 commented on July 19, 2024

Hey @hailwood,

Sorry for the delayed response! You are correct that you don't necessarily paginate a list alone, but you can create a new Type to get it work and w/ Lighthouse you have two options.

Regular Pagination

First, you can create your own Type that has the fields required for pagination (such as page, total, etc) plus the listOf containing a list of the GraphQL type you want to provide. For example:

class UserTasks extends GraphQLType
{
    /**
     * Attributes of Type.
     *
     * @var  array
     */
    protected $attributes = [
        'name' => 'UserTasks',
    ];

    // ...

    /**
     * Available fields of Type.
     *
     * @return  array
     */
    public function fields()
    {
        return [
            'page' => [
                'type' => Type::int(),
            ],
            'count' => [
                'type' => Type::int(),
                'description' => 'How many tasks to paginate',
            ],
            'total' => [
                'type' => Type::int(),
                'description' => 'Total number of user tasks.',
            ],
            'tasks' => [
                'type' => Type::listOf(GraphQL::type('task'))
            ],
        ];
    }
}

Then (in this example) you would just register it and attach it to your UserType and add some arguments like so:

// fields on UserType
[
    // ..
    'tasks' => [
        'type' => GraphQL::type('userTasks'),
        'args' => [
            'page' => [ 'type' => Type::int() ],
            'count' => [ 'type' => Type::int() ],
        ],
        'resolve' => function (User $user, array $args) {
            $count = array_get($args, 'count', 15);
            $page = array_get($args, 'page', 1);
            $tasks = $user->tasks()->paginate($count, ['*'], 'page', $page);

            return [
                'page' => $tasks->currentPage(),
                'count' => $tasks->count(),
                'total' => $tasks->total(),
                'tasks' => $tasks->items(),
            ];
        }
    ],
]

Relay Pagination

Alternatively, you can use Lighthouse's built in connection helper which matches the Relay spec. First, you need to add the RelayConnection Trait to the model you want to paginate over (in this case it would be the Task model;

use Illuminate\Database\Eloquent\Model;
use Nuwave\Lighthouse\Support\Traits\RelayConnection;

class Task extends Model
{
    use RelayConnection;

    // ...
}

Then create a new connection

$ php artisan lighthouse:connection UserTasks

Customize the generated connection

namespace App\Http\GraphQL\Connections;

use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Interfaces\Connection;

class UserTasks implements Connection
{
    /**
     * Get the name of the connection.
     * Note: Connection names must be unique
     *
     * @return string
     */
    public function name()
    {
        return 'UserTasks';
    }

    /**
     * Get name of connection.
     *
     * @return string
     */
    public function type()
    {
        return 'task';
    }

    /**
     * Available connection arguments.
     *
     * @return array
     */
    public function args()
    {
        return [];
    }

    /**
     * Resolve connection.
     *
     * @param  mixed  $parent
     * @param  array  $args
     * @param  mixed  $context
     * @param  ResolveInfo $info
     * @return mixed
     */
    public function resolve($user, array $args, $context, ResolveInfo $info)
    {
        // we have access to `getConnection` here because of the trait we added
        return $user->tasks()->getConnection($args);
    }
}

and finally, just add the connection as a field to the UserType

[
    // ...
    'tasks' => GraphQL::connection(new App\Http\GraphQL\Connections\UserTasks())->field(),
]

That's it! It will create a new Connection Type that has all of the required Relay fields for a connection!

Hopefully that helped, but let me know if you still have questions!

from lighthouse.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.