Have any questions:

Toll free:9801887718Available 24/7

Email our experts:info@mantraideas.com

In: Laravel, Web Development

In the previous blog, we explored the key differences between REST API and GraphQL – what makes GraphQL exciting, and why it’s gaining much attention among modern developers. 

In this tutorial, we’ll take the next big step: Implement GraphQL in Laravel using the powerful Lighthouse package. This guide will walk you through the setup, default schema testing, and building custom queries and mutations with resolvers. 
If you’re getting started with GraphQL in Laravel, buckle up – this is the Laravel GraphQL example you’ve been looking for.

Create a Laravel project

  • PHP 8+
  • Laravel 9 or higher

Create a Laravel project

composer create-project laravel/laravel graphql-demo

Install the lighthouse package

composer require nuwave/lighthouse

Publish the Schema & Config Files

Publish the default GraphQL schema:

php artisan vendor:publish –tag=lighthouse-schema

Publish the configuration file:

php artisan vendor:publish –tag=lighthouse-config

Configure the GraphQL Endpoint

Go to config/lighthouse.php  file and locate the route array. The default URI is:   

'uri' => '/graphql'
You can change this to something like /api/graphql, or any of your choice. But for this tutorial, we’ll use the default.

Explore the Default Schema

After publishing, a new graphql/ folder will appear in your root directory. Inside, you’ll find a file named schema.graphql.

It includes a default type and query for the User model. Let’s test this out by seeding some dummy users.

Seed the Database with Users

 php artisan make:seeder UserTableSeeder

Update the run() method in the seeder:

public function run(): void
{
   $userData = [
       [
           'name' => 'John Doe',
           'email' => 'johndoe@gmail.com',
           'password' => Hash::make('password'),
       ],
       [
           'name' => 'Harry Doe',
           'email' => 'harrydoe@gmail.com',
           'password' => Hash::make('password'),
       ],
       [
           'name' => 'Kate Doe',
           'email' => 'katedoe@gmail.com',
'password' => Hash::make('password'),
       ],
       [
           'name' => 'Emily Doe',
           'email' => 'emilydoe@gmail.com',
           'password' => Hash::make('password'),
       ],
   ];


   foreach ($userData as $user) {
       User::create($user);
   }
}

Run the seeder:

php artisan db:seed –class=UserTableSeeder

Test the Default Queries

You can now test the default schema using any GraphQL client. I prefer Altair, but you can also use GraphiQL, Insomnia, or Postman.

Try the following queries for testing:

query user{

    user(id: "1")

    {

      id

      name

      email

    }

}
query Users {

  users {

    data {

      name

      email

    }

    paginatorInfo {

      total

      currentPage

      lastPage

    }

  }

}

See how powerful this is? You didn’t have to write a single controller or route. Just define the schema, and you’re good to go. 

But if you do want to customize logic — let’s say you want more control — you can build custom resolvers.

Create a Post Model with Migration

Let’s create a new model Post and add a relationship to the user

php artisan make:model Post -m

In the migration file:

public function up(): void
{
   Schema::create('posts', function (Blueprint $table) {
       $table->id();
       $table->string('title');
       $table->string('description');
       $table->unsignedBigInteger('added_by');
       $table->boolean('status')->default(false);
       $table->timestamps();
       $table->foreign('added_by')->references('id')->on('users')->onDelete('cascade');
   });
}

Run the migration: 

php artisan migrate

Define the relationship in the Post model:

public function user():BelongsTo
{
   return $this->belongsTo(User::class,'added_by');
}

Define a Custom Mutation

Update schema.graphql

type Post{
   id: ID!
   title: String!
   description: String!
   added_by: ID!
   status: Boolean!
}


type Mutation {
   createPost(input: PostInput!): Post @field(resolver: "App\\GraphQL\\Mutations\\PostMutation@store")
}


input PostInput{
   title: String!
   description: String!
   status: Boolean
}

Generate the mutation class:

php artisan lighthouse:mutation PostMutation

It will create a new file as: app/GraphQL/Mutations/PostMutation.php

Inside PostMutation.php, add store method as: 

public function store($_, array $args)
{
   $input = $args['input'];
   $post = Post::create([
       'title' => $input['title'],
       'description' => $input['description'],
       'added_by' => 1, // the id of authenticated user
       'status' => $input['status'],
   ]);
   $post->load('user');
   return $post;
}

Now you can test the mutation as follows:

mutation createPost{

  createPost(input:{

  title: "My new post"

  description:"This is the description"

  status: true

}){

  title

  description

  status

  user{

    id

    name

    email

  }

}

}


The output will look something like this:

Define Custom Query Resolvers

In your schema.graphql

type Query {
   post(id: ID! @eq): Post @find	
   posts(search: String): [Post!]! @field (resolver:"App\\GraphQL\\Queries\\PostQuery@getActivePosts")
}

Generate the query class:

php artisan lighthouse:query PostQuery

This will create a new class as app/GraphQL/Queries/PostQuery.php

In the PostQuery.php file, add the following

public function getActivePosts($_, array $args)
{
   $query = Post::with('user')->where('status',true);
   if($args['search'])
   {
       $posts = $query->where('title', 'LIKE', '%'.$args['search'].'%');
   }
   $posts = $query->latest()->get();
   return $posts;
}

Test the query as follows:

query post{

  post(id: 1){

  title

  description

  status

  user{

    name

    }

  }

}
query posts{

  posts(search: "first"){

    id

      title

  description

  status

  user{

    name

    }

  }

}

Wrapping Up

And there you go! You now have a fully functional Laravel GraphQL API in Laravel using Lighthouse.

With just a few commands and schema definitions, you can:

  • Query data with precision
  • Avoid over-fetching
  • Add custom logic via resolvers
  • Keep your backend clean and scalable

And the best part? You’ve done this using GraphQL in Laravel, a truly modern combo.

You can now expand further with:

  • @auth / @guard for role-based access
  • Custom middleware
  • Enum types
  • Custom directives
  • Connect a Laravel GraphQL client like Apollo or urql for seamless frontend integration
  • Connect GraphQL with Laravel MySQL databases directly

For more info, check out the official Lighthouse docs.

Conclusion

REST APIs still have their place, but when it comes to fine-grained control, developer speed, and frontend happiness — GraphQL in Laravel shines bright.

Whether you’re working on enterprise-level apps or just starting with your Laravel GraphQL example, the stack is flexible, clean, and super fun to use.

Give it a try, and happy coding!

Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *