Fields

To fetch data from your GraphQL endpoint, you need to define resolvers for your fields. Lighthouse makes this easy by providing easy to use, pre-built resolvers that work great together with your Eloquent models.

Hello World!

As is the tradition of our people, this section will teach you how to say "hello world!" through Lighthouse. The following schema defines a simple field called hello that returns a String.

type Query {
  hello: String! 
}

You need to implement the actual resolver next. Lighthouse looks for a class with the capitalized name of the field in App\GraphQL\Queries and calls its resolve function.

<?php

namespace App\GraphQL\Queries;

class Hello
{
    public static function resolve(): string
    {
        return 'world!';
    }
}

Now your schema can be queried.

{
  hello
}

And will return the following response:

{
  "data": {
    "hello": "world!"
  }
}

Query data

Lighthouse provides many resolvers that are already built-in, so you do not have to define them yourself. The following is not a comprehensive list of all resolvers but should give you an idea of what you can do.

Fetch a list of models

Since you are already using Laravel, you might as well use Eloquent to fetch the data for your Query. Let's say you defined your User type like this:

type User {
  id: ID!
  name: String!
}

Instead of defining your own resolver manually, you can just rely on Lighthouse to build the Query for you.

type Query {
  users: [User!]! @all
}

The @all directive will assume the name of your model to be the same as the return type of the Field you are trying to resolve and automatically uses Eloquent to resolve the field.

The following query:

{
  users {
    id
    name
  }
}  

Will return the following result:

{
  "data": {
    "users": [
      {"id": 1, "name": "James Bond"},
      {"id": 2, "name": "Madonna"}
    ]
  }
}

Query with arguments

You may have noticed how every field has to have a resolver function. In many ways, fields are similar to functions. Just like functions, fields can take arguments to make them more flexible.

The following field allows you to fetch a single User by ID.

type Query {
  user(id: ID! @eq): User @find
}

You can query this field like this:

{
  user(id: 69){
    name
  }
}

And, if found, receive a result like this:

{
  "data": {
    "user": {
      "name": "Chuck Norris"
    }
  }
}

Mutate data

Per convention, a GraphQL Query is not allowed to change data. You will need to define a Mutation for that. Mutations look just like queries, but only they can create, update or delete data.

The following examples will show you how to make changes to a single model. If you need to save multiple related models at once, look into Mutating Relationships.

Create

The easiest way to create data on your server is to use the @create in combination with an existing Laravel model.

type Mutation {
  createUser(name: String!): User! @create
}

This will take the arguments that the createUser field receives and use them to create a new model instance.

mutation {
  createUser(name: "Donald"){
    id
    name
  }
}

The newly created user is returned as a result:

{
  "data": {
    "createUser": {
      "id": "123",
      "name": "Donald"
    }
  }
}

Update

You can easily add a way to update your data with the @update directive.

type Mutation {
  updateUser(id: ID!, name: String): User @update
}

Since GraphQL allows you to update just parts of your data, it is best to have all arguments except id as optional.

mutation {
  updateUser(id: "123" name: "Hillary"){
    id
    name
  }
}
{
  "data": {
    "updateUser": {
      "id": "123",
      "name": "Hillary"
    }
  }
}

Be aware that while a create operation will always return a result, provided you pass valid data, the update may fail to find the model you provided and return null:

{
  "data": {
    "updateUser": null
  }
}

Delete

Deleting data through your GraphQL API is really easy with the @delete directive. Dangerously easy.

type Mutation {
  deleteUser(id: ID!): User @delete
}

Simply call it with the ID of the user you want to delete.

mutation {
  deleteUser(id: "123"){
    secret
  }
}

This mutation will return the deleted object, so you will have a last chance to look at the data. Use it wisely.

{
  "data": {
    "deleteUser": {
      "secret": "Pink is my favorite color!"
    }
  }
}

Subscribe to data

Lighthouse allows you to serve GraphQL subscriptions. Compared to queries and mutations, a more elaborate setup is required.

Read more about how to set up subscriptions

Custom resolvers

Sometimes, the built-in directives just don't cut it - you need more control! Lighthouse allows you to implement your own resolver function for fields.

By default, Lighthouse looks for a class with the capitalized name of the field in App\GraphQL\Queries or App\GraphQL\Mutations and calls its resolve function with the usual resolver arguments. If you stick to that convention, you will not need to specify a directive at all.

For example, the following field:

type Query {
  latestPost: Post!
}

expects a class like this:

<?php

namespace App\GraphQL\Queries;

use App\Post;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class LatestPost
{
    public function resolve($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Post
    {
        return Post::orderBy('published_at', 'DESC')->first();
    }
}

The easiest way to create such a class is to use the built in artisan commands lighthouse:query and lighthouse:mutation. They both take a single argument: the name of the field you want to generate.

For example, this is how you generate a class for the field latestPost:

php artisan lighthouse:query LatestPost

If you need to implement custom resolvers for fields that are not on one of the root types Query or Mutation, you can use the @field directive.