In case you’re still not familiar with it, GraphQL is a query language used to interact with your API which provides some benefits compared to alternative architectures such as REST. GraphQL is extremely handy when used to serve as an endpoint for mobile and single-page applications. GraphQL allows you to query nested and related data in a request with relative ease, allowing developers to obtain the exact data they need in a single round trip to the server.
Laravel is a popular, opinionated PHP web framework. It provides numerous built-in tools to get applications up and running quickly, but it also allows developers to swap out their own implementations for Laravel’s built-in interfaces when preferred.
Although the communities surrounding both GraphQL and Laravel have grown dramatically since they were open-sourced, documentation explaining how to use these two technologies together is still somewhat scarce.
So, in this tutorial, I will show you how to create your own GraphQL server using Laravel.
Before we get started, we’ll need to get familiar with the project we are attempting to build. To do that, we will define our resources and create our GraphQL schema, which we will later use to serve our API.
Our application will consist of two resources: Articles and Users. These resources will be defined as object types in our GraphQL schema:
Looking at the schema, we can see that we have a one-to-many relationship between our two objects. Users can write many articles, and an article has an author (user) assigned to it.
Now that we have our object types defined, we’ll need a way to create and query our data, so let’s define our query and mutation objects:
Now that we’ve defined our GraphQL schema, let’s get our Laravel project up and running. Let’s start by creating a new Laravel via Composer project:
Just to make sure we have everything working, let’s boot up our server and make sure we see Laravel’s default page:
For the purposes of this article, we will be using SQLite. So, let’s make the following changes to the default
Next, let’s create our database file:
Laravel ships with a user model and some basic migration files. Let’s quickly add an
api_token column to our in our
CreateUsersTable migration file provided to us by Laravel:
We’ll circle back to this additional column later on in the article when we get to authorization. Now let’s go ahead and create our article model and a migration file to create the associated table:
Note: The -m option creates a migration file for our newly created article model.
Let’s make some adjustments to the generated migration file:
We’ve added a foreign key pointing to the
id on our
users table as well as the
content columns we defined in our GraphQL schema.
Now that we have our migration files defined, let’s go ahead and run them against our database:
Next, let’s update our models by defining the necessary relationships:
Now that we have our models and migrations set up, let’s seed our database. We’ll start by creating some seeder classes for our
Next, let’s set them up to insert some dummy data into our SQLite database:
Finally, let’s go ahead and run our database seeders to get some data into our database:
Now that we have our database and models set up, it’s time to start building out our GraphQL server. Currently, there are several solutions available for Laravel, but for this article, we’re going to use Lighthouse.
Lighthouse is a package I created a few years ago and has recently seen some amazing support from the growing community around it. It allows developers to quickly set up a GraphQL server using Laravel with little boilerplate while also being flexible enough to allow developers to customize it to fit the needs of just about any project.
Let’s start by pulling the package into our project:
Next, let’s publish Lighthouse’s configuration file:
Note: You can also choose to publish Lighthouse’s default schema file by simply removing the
--tag=config option. But for the purposes of this article, we are going to create our schema file from scratch.
If we take a look at the
config/lighthouse.php file you’ll notice a setting used to register our schema file with Lighthouse:
So let’s go ahead and create our schema file and set up our user object type and query:
You’ll notice that our schema looks similar to the one we defined earlier except we’ve added some identifiers called schema directives.
Let’s take a moment to break down our defined schema. Our first definition is an object type called
User which has a relation to our
App\User eloquent model. We defined the
User models. Alternatively, this means that the
updated_at columns are fields that cannot be queried for from our API.
Next we have our
Query type which is an entry point into our API and can be used to query for data. Our first field is the
users field which returns an array of
User object types. The
@all directive tells Lighthouse to run an Eloquent query, using our
User model and get all of the results. This would be the same as running the following:
Note: Lighthouse knows to look for a model in the
\App\User namespace because of the
namespaces option defined in its configuration file.
Our second defined field on our query type is the call
user, which takes an
id as an argument and returns a single
User object type. We’ve also added two directives to help Lighthouse automatically build a query for us and return a single
User model. The
@eq directive tells Lighthouse to add a where on our
id column, and the
@find directive instructs Lighthouse to return a single result. To write this query using Laravel’s query builder, it would look like this:
Now that we have a bit of insight into how Lighthouse uses our schema to create queries, let’s run our server and start querying data. We’ll start by running our server:
To query a GraphQL endpoint, you could run cURL command in the terminal or a standard client such as Postman. However, to get the full benefits of GraphQL (such as autocomplete, error highlighting, documentation, etc., we’ll use GraphQL Playground (release downloads here).
When starting up Playground, click on the “URL Endpoint” tab, and type in http://localhost:8000/graphql to point GraphQL Playground to our server. On the left side of the editor, we can query for our data, so let’s start by asking for all the users that we seeded the database with:
When you hit the play button in the middle of the IDE (or click Ctrl+Enter), you’ll see the JSON output of our server on the right side, which will look something like this:
Note: Because we used Faker to seed our database, the data in the
name fields will be different.
Now let’s try querying for a single user:
And we’ll get the following output for a single user:
Querying for data like this is nice to get started with, but it’s highly unlikely you’ll be in a project where you would ever want to query for all of your data, so let’s try to add in some pagination. When looking through Lighthouse’s wide range of built-in directives, we have a
@paginate directive readily available to us, so let’s update our schema’s query object like so:
If we reload GraphQL Playground (Ctrl/Cmd + R) and try our
users query again, you’ll notice that we get an error message stating
Cannot query field "id" on type "UserPaginator", so what happened? Behind the scenes, Lighthouse manipulates our schema for us to get a paginated set of results and does so by changing the return type of our
Let’s take a closer look by inspecting our schema in GraphQL Playground’s “Docs” tab. If you take a look at the
users field, it is returning a
UserPaginator which returns an array of users and a Lighthouse defined
If you’re familiar with Laravel’s built-in pagination, the fields available in the
PaginatorInfo type will probably look very familiar to you. So, to query for two users, get the total number of users in the system, and check we have more pages to cycle through, we would send the following query:
Which will provide us with the following response:
Generally, when developing an application, much of your data is related. In our case, a
User can write many
Articles, so let’s add that relationship to our User type and define our
Here, we’re using another Lighthouse provided schema directive
@hasMany, which tells Lighthouse our
User model has a
\Illuminate\Database\Eloquent\Relations\HasMany relationship with the
Now let’s query our newly defined relationship:
This will provide us with the following response:
Finally, let’s reverse our relationship and add our
author relationship to our
Article object type using Lighthouse’s
@belongsTo schema directive as well as updating our
You’ll see that we added an optional
relation argument to the
@belongsTo directive. This tells Lighthouse to use the
user relationship and assign it to the
Now let’s query for a list of articles and grab their associated author:
And we should get the following from our server:
Now that we can query our data, let’s create some mutations to create some new users and articles. We’ll start with our user model:
Now let’s break this schema definition down. We’ve created a mutation called
createUser which takes three arguments (
password). We’ve applied the
@rules directive to both our
password arguments. This may look a bit familiar because it’s similar to the validation logic Laravel provides for its controllers.
Next, we’ve attached the
@bcrypt directive to our
password field. This will encrypt the password before it is passed to the newly created model.
Finally, to help us create new models, Lighthouse provides a
@create schema directive which will take the arguments we defined and create a new model. Performing the same logic in a Controller would look like the following:
Now that we have our createUser mutation field set up, let’s go ahead and run it in GraphQL Playground with the following:
We should get the following output:
Since we need to add a
user_id to our
Article models, now would be a great time to go over authentication and authorization in GraphQL/Lighthouse.
To authenticate a user, we need to provide them with an
api_token, so let’s create a mutation to handle that and we’ll add the
@field directive to point Lighthouse to a custom resolver which will handle the logic. We set the resolver in the same pattern as defining a controller in Laravel using the
@field directive defined below, we’re telling Lighthouse when the
login mutation is run, use the
createToken method on our
Note: You do not need to include the entire namespace here. In the
lighthouse.php config file you’ll see we have the namespace defined for our mutations set as
App\\GraphQL\\Mutations already—however, you could use the full namespace if you prefer.
Let’s use Lighthouse’s generator to create the new mutator class:
Next, let’s update our resolver function like so:
Now that we have our resolver set up, let’s test it out and try to obtain an API token using the following mutation in GraphQL Playground:
We should get a token sent back to us like so:
Note: Be sure to copy the token returned from the login mutation so we can use it later.
Next, let’s add a query field which will return the authenticated user to make sure our logic works. We’ll add a field called
me and use Lighthouse’s
@auth directive to return the currently authenticated user. We’ll also set the
guard argument equal to
api since that is how we will authenticate the user.
Now let’s run the query. In GraphQL Playground, you can set your request headers by double clicking the “Http Headers” tab at the bottom. We add headers with a JSON object, so to add a bearer token to each request, you would add the following:
Note: Replace the bearer token with the token you received when running the login query.
Now let’s run the
We should get output that looks like this:
Now that we know our authentication is working properly, let’s create our last mutation to create an article using the currently authenticated user. We’ll use the
@field directive to point Lighthouse to our resolver and we’ll also include a
@middleware directive to ensure that a user is logged in.
First, let’s generate a mutation class:
Next, let’s update the mutator with the following logic:
Note: We renamed the default
resolve function to
create. You don’t need to create a new class for every resolver. Instead, you can group logic together if it makes more sense.
Finally, let’s run our new mutation and check the output. Be sure to keep the
Authorization header from our previous query in the “HTTP Headers” tab:
We should get the following output:
To recap, we’ve leveraged Lighthouse to create a GraphQL server for our Laravel project. We made use of some built in schema directives, created queries and mutations, and handled authorization and Authentication.
Lighthouse allows you to do much more (such as allowing you to create your own custom schema directives) but for the purposes of this article we stuck to the basics and we were able to get a GraphQL server up and running with fairly little boilerplate.
The next time you need to set up an API for a mobile or single-page application, be sure to consider GraphQL as a way to query your data!
This content was originally published here.