Hello, web developers! In this tutorial, I’ll walk you through the process of building a headless API in Laravel using GraphQL. While REST APIs are more commonly used, GraphQL offers more flexibility by allowing the client to specify exactly what data it needs.
We’ll be setting up GraphQL endpoints in Laravel and structuring queries that can be consumed by frontend frameworks like React or Vue.js. Let’s dive into it!
First, let’s start by creating a new Laravel project. If you already have one, you can skip this step.
composer create-project --prefer-dist laravel/laravel graphql-api
Next, we need to install the nuwave/lighthouse
package to integrate GraphQL in our Laravel project.
composer require nuwave/lighthouse
After the installation, publish the configuration file:
php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider"
This will create a lighthouse.php
configuration file where we can customize GraphQL settings.
GraphQL requires a schema file to define types, queries, and mutations. You can find this file in graphql/schema.graphql
. Let’s create a simple User
type and a query to fetch users.
type User {
id: ID!
name: String!
email: String!
}
type Query {
users: [User!]! @all
}
Here, we’ve defined a User
type with fields like id
, name
, and email
. The @all
directive tells Laravel to fetch all users from the database.
Next, we’ll create a model and migration for the users
table. Run the following artisan command:
php artisan make:model User -m
In the generated migration file, define the fields for the users
table:
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamps();
});
Run the migration to create the users
table:
php artisan migrate
To test the API, let’s seed some dummy data into the users
table. You can create a seeder using the following command:
php artisan make:seeder UserSeeder
In the seeder file, add the following code to insert dummy users:
use App\Models\User;
use Illuminate\Database\Seeder;
class UserSeeder extends Seeder {
public function run() {
User::factory()->count(10)->create();
}
}
Run the seeder to insert the data:
php artisan db:seed --class=UserSeeder
Now that we’ve set up the schema, let’s test our GraphQL API. Run the development server:
php artisan serve
Navigate to http://localhost:8000/graphql-playground
to access the GraphQL Playground interface. You can now test the users
query:
{
users {
id
name
email
}
}
This query will fetch the list of users from the database, returning only the id
, name
, and email
fields.
Now that we have a working GraphQL API, let’s integrate it with a frontend framework like React or Vue.js.
React Example (Using Apollo Client)
Install Apollo Client
to handle GraphQL queries in React:
npm install @apollo/client graphql
Here’s an example of how you can fetch users in React:
import React from 'react';
import { ApolloClient, InMemoryCache, ApolloProvider, useQuery, gql } from '@apollo/client';
const client = new ApolloClient({
uri: 'http://localhost:8000/graphql',
cache: new InMemoryCache()
});
const USERS_QUERY = gql`
query {
users {
id
name
email
}
}
`;
function Users() {
const { loading, error, data } = useQuery(USERS_QUERY);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>Users</h1>
<ul>
{data.users.map(user => (
<li key={user.id}>{user.name} ({user.email})</li>
))}
</ul>
</div>
);
}
function App() {
return (
<ApolloProvider client={client}>
<Users />
</ApolloProvider>
);
}
export default App;
Vue.js Example (Using Apollo Client)
For Vue.js, you can install Apollo
and GraphQL
similarly:
npm install @vue/apollo-composable @apollo/client graphql
Here’s an example of fetching users in Vue.js:
<template>
<div>
<h1>Users</h1>
<ul>
<li v-for="user in users" :key="user.id">{{ user.name }} ({{ user.email }})</li>
</ul>
</div>
</template>
<script>
import { useQuery, gql } from '@vue/apollo-composable';
export default {
setup() {
const USERS_QUERY = gql`
query {
users {
id
name
email
}
}
`;
const { result } = useQuery(USERS_QUERY);
return {
users: result.users
};
}
};
</script>
You might also like: