Writing Complex GraphQL Queries and Mutations in Laravel



GraphQL provides a flexible and efficient way to interact with APIs, allowing clients to request the data they need. In Laravel, the Lighthouse package makes it easy to implement GraphQL. This article will guide you through writing complex GraphQL queries and mutations in a Laravel application.


Understanding GraphQL


GraphQL, developed by Facebook, is a query language for APIs that enables clients to request specific data structures. It consists of three main components:


1. Queries: For fetching data.

2. Mutations: For modifying data.

3. Subscriptions: For real-time data updates.


Setting Up GraphQL with Laravel


Before diving into complex queries and mutations, ensure you have GraphQL set up in your Laravel application using the Lighthouse package.


1. Install Lighthouse:

   composer require nuwave/lighthouse


2. Publish Configuration:

   php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider"


3. Define Schema:

   Create and define your GraphQL schema in the `graphql/schema.graphql` file.


Writing Complex GraphQL Queries


Complex queries often involve fetching nested and related data, filtering, sorting, and pagination. Let's explore these aspects with examples.


Example Schema:


type Query {

    users(filter: UserFilter, sort: UserSort, paginate: PaginateInput): UserConnection

    user(id: ID!): User

}


type User {

    id: ID!

    name: String!

    email: String!

    posts: [Post!]!

}


type Post {

    id: ID!

    title: String!

    body: String!

    comments: [Comment!]!

}


type Comment {

    id: ID!

    content: String!

}


input UserFilter {

    name: String

    email: String

}


input UserSort {

    field: String

    order: String

}


input PaginateInput {

    page: Int

    limit: Int

}


type UserConnection {

    data: [User!]!

    paginatorInfo: PaginatorInfo!

}


type PaginatorInfo {

    count: Int!

    currentPage: Int!

    lastPage: Int!

    perPage: Int!

    total: Int!

}


Complex Query Example:


query {

    users(filter: { name: "John" }, sort: { field: "email", order: "ASC" }, paginate: { page: 1, limit: 10 }) {

        data {

            id

            name

            email

            posts {

                id

                title

                comments {

                    id

                    content

                }

            }

        }

        paginatorInfo {

            count

            currentPage

            lastPage

            perPage

            total

        }

    }

}


Resolvers:


namespace App\GraphQL\Resolvers;


use App\Models\User;

use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;


class UserResolver

{

    public function users($root, array $args, GraphQLContext $context)

    {

        $query = User::query();


        // Apply filtering

        if (isset($args['filter'])) {

            if (isset($args['filter']['name'])) {

                $query->where('name', 'like', '%' . $args['filter']['name'] . '%');

            }

            if (isset($args['filter']['email'])) {

                $query->where('email', 'like', '%' . $args['filter']['email'] . '%');

            }

        }


        // Apply sorting

        if (isset($args['sort'])) {

            $query->orderBy($args['sort']['field'], $args['sort']['order']);

        }


        // Apply pagination

        $pagination = $query->paginate($args['paginate']['limit'] ?? 15, ['*'], 'page', $args['paginate']['page'] ?? 1);


        return [

            'data' => $pagination->items(),

            'paginatorInfo' => [

                'count' => $pagination->count(),

                'currentPage' => $pagination->currentPage(),

                'lastPage' => $pagination->lastPage(),

                'perPage' => $pagination->perPage(),

                'total' => $pagination->total(),

            ],

        ];

    }


    public function user($root, array $args, GraphQLContext $context)

    {

        return User::findOrFail($args['id']);

    }

}


Writing Complex GraphQL Mutations


Mutations in GraphQL allow you to create, update, or delete data. Complex mutations may involve nested inputs, validations, and transactions.


Example Schema:


type Mutation {

    createUser(input: CreateUserInput!): User

    updateUser(id: ID!, input: UpdateUserInput!): User

}


input CreateUserInput {

    name: String!

    email: String!

    posts: [CreatePostInput!]!

}


input CreatePostInput {

    title: String!

    body: String!

    comments: [CreateCommentInput!]!

}


input CreateCommentInput {

    content: String!

}


input UpdateUserInput {

    name: String

    email: String

}


type User {

    id: ID!

    name: String!

    email: String!

    posts: [Post!]!

}


Complex Mutation Example:


mutation {

    createUser(input: {

        name: "John Doe",

        email: "john@example.com",

        posts: [{

            title: "My First Post",

            body: "This is the body of my first post",

            comments: [{

                content: "Great post!"

            }]

        }]

    }) {

        id

        name

        email

        posts {

            id

            title

            comments {

                id

                content

            }

        }

    }

}


Resolvers:


namespace App\GraphQL\Resolvers;


use App\Models\User;

use App\Models\Post;

use App\Models\Comment;

use Illuminate\Support\Facades\DB;

use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;


class UserResolver

{

    public function createUser($root, array $args, GraphQLContext $context)

    {

        return DB::transaction(function () use ($args) {

            $user = User::create($args['input']);


            if (isset($args['input']['posts'])) {

                foreach ($args['input']['posts'] as $postInput) {

                    $post = new Post($postInput);

                    $user->posts()->save($post);


                    if (isset($postInput['comments'])) {

                        foreach ($postInput['comments'] as $commentInput) {

                            $comment = new Comment($commentInput);

                            $post->comments()->save($comment);

                        }

                    }

                }

            }


            return $user;

        });

    }


    public function updateUser($root, array $args, GraphQLContext $context)

    {

        $user = User::findOrFail($args['id']);

        $user->update($args['input']);

        return $user;

    }

}




Writing complex GraphQL queries and mutations in Laravel using the Lighthouse package provides a powerful way to interact with your application's data. You can efficiently manage and query your data by defining a detailed schema, creating resolvers, and leveraging GraphQL's flexibility. This approach improves performance and enhances the developer and user experience by providing precise and efficient data fetching and manipulation capabilities. Embrace GraphQL to take your Laravel application to the next level.