Recently I have been working on something very amazing for API development, everyone has been using REST to access API, but now things are changing, in the front-end heavy world where things are consistently growing and new features added every week a fixed REST API is not very good option anymore, so what we need then? the answer is GraphQL. Let’s dive into details of this amazing query language and build a Twitter like app API in Laravel using GraphQL.
You will implement the GraphQL API by using Laravel, one of the most popular PHP frameworks that allows you to set up an application in minutes by exploiting its powerful infrastructure. Finally, you will learn how easy it is to secure your GraphQL API with Auth0. 2/3) Master Laravel with Vue.js Fullstack Development - next step with your Laravel learning - introducing Vue.js, creating APIs and SPAs - already knowing a little bit of Laravel would be very helpful. 2/3) Master Laravel with GraphQL, Vue.js, and Tailwind - learn GraphQL - an alternative to REST APIs, Tailwind CSS, and continue working with Vue.
What is GraphQL?
GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. GraphQL isn’t tied to any specific database or storage engine and is instead backed by your existing code and data. It was created by Facebook to fulfill growing needs of API consumption and it has been implemented in major languages.
At the heart of any GraphQL implementation is a description of what types of objects it can return, described in a GraphQL type system and returned in the GraphQL Schema. For example here is a User type which we will use later in this post.
When will i be able to download my video? Its been 24 hours now and i stil cant download it i dont want to take 3 days break from cs just so i can download a video of me playing well so how long do i have to wait? How to fix corrupt download cs gonewpride.
GraphQL queries declaratively describe what data the issuer wishes to fetch from whoever is fulfilling the GraphQL query. For example, if you want to get User with
name you can query it like this:
which will give us only the name and id of users like this:
Most discussions of GraphQL focus on data fetching, but any complete data platform needs a way to modify server-side data as well, mutation can do that. These are set of queries which can perform create, update & delete on the database.
Above mutation will create a User and return back the id, email & name.
Now let’s see how we can use this in a Laravel App, I am going to use Laravel 5.4 and to implement server of GraphQL I am going to use laravel-graphql package. This PHP implementation is a thin wrapper around your existing data layer and business logic. It doesn’t dictate how these layers are implemented or which storage engines are used. Instead, it provides tools for creating API for your existing app.
Create a new Laravel 5.4 App and once installed configure a database and install laravel-graphql package using composer.
Once that’s installed, add service provider and alias for the facade.
Now let’s publish our GraphQL config file
That completes installation and everything is setup. Let’s move on the Model and Migration.
We will be building a tweeter like an app DB schema, let’s add an avatar field on provided User model and create Profile, Tweet, Reply & Like model with migration.
Now let’s fill up the migration schema in all stubs.
I have gone ahead and created Model factory and Database seeder for this. Run the
php artisan db:seed to seed dummy data.
Now laravel stuff out of the way lets now start defining the Types for User to use with GraphQL.
Let’s define the UserType, we need to create our class in
Let me explain whats going on, GraphQL need 2 things to return data for a field, first is a
fields and second is a
resolver function which will get the data from the database for that field. In above class
fields() method we are returning a fields schema for user, only fields added here will be returned by GraphQL API.
And below fields() we have resolver overrides, for example I have used
resolveEmailField() method to format the email to make it lowercase. It’s like Accessor in Eloquent model, and after this we have some nested resources tweets and profile which are resolved by
resolveTweetsField() method and
In Tweets resolver, we have some argument checking, which will be passed from the query and we return the has many relation tweets data from $root which is User model instance here.
Once you defined all the type you need to add them in
config/graphql.php files under
types array, thats how GraphQL will know about available types.
Cool, now we have our Types, let’s define our Queries so we can access data through API call using GraphQL.
We want to create a query which will be for only reading data. Let’s define one to access Users, create a class under below namespace.
For sake of simplicity I have added all the resolver data fetching logic in the method, you should consider a service class to delegate fetching of data so later you can add caching etc.
This looks very similar to UserType class but it will be use to fetch the actual data, so first, we define the Type we are going to return in
type() method, in this case it will be
Type::listOf(GraphQL::type('User')). Next we define all of the argument this query can take in
args() method. In here we have
id which we can use to filter user by id,
first which will be used to limit the result by number.
Once you defined your Query, let’s once again add it in
config/graphql.php under schemas default queries array.
GraphQL users query
Now we can open a browser and get the user data. Let’s get all the users with
name, by default you can access on
http://localhost:8000/graphql route, you can change this in
graphql.php config file.
I am running on localhost:8000, you need to match your dev app url to test it.
Here is how our query looks like:
and a request URL will be like this
If you did everything right you will get the list of users, if something is wrong you will get an error with a message.
If you remember in query definition, we had some arguments, let’s use them. First let’s limit the result to only 5 users, passing first:5 will do the trick.
Find user by ID or Email
You can also find a specific user by
Access Nested Resource
Accessing the nested resource where GraphQL shines, in UserType we have defined
profile as nested resource. Let see how we can get them in a query.
Similarly, you can access tweets of a user, let’s access first 3 tweets for a user.
Power of GraphQL queries
As you can see you have lots of flexibility in terms of what exactly you need, if you do the same thing in REST API you probably need 3 different HTTP request to get all the things you needed or create some sort of alias endpoint on API to get
userWithTweet and another for
userWithProfile. It will make more difficult to change front-end of app since data need has changed, now you probably need another API endpoint with
userProfileAndTweets. As you can see it can get very messy very quickly. But with GraphQL you don’t need any other endpoint, it will be most likely will be a single endpoint and queries declaratively describe what data the issuer wishes to fetch.
Now we have a solid understanding how to fetch data, but what about making a change in data or persist new record.
Mutation in GraphQL
Let’s define the mutation to
Let’s create a file in
app/GraphQL/Mutation/CreateUserMutation.php and add below code.
Mutation needs to mutate the data so it has one more
rules() method to validate the data, you can use laravel validation with a resolve function that does the data manipulation in the database. In this case, we create a user if data is valid. Let’s see it in action.
As we did for queries, let’s add the mutation in
config/graphql.php file under schemas default mutations array.
To create a user we need to send the user data, its looks like query but this time we have to pass key value pairs, unlike in query you just ask for fields.
In this createUser mutation we create the user and in next block, we are asking to return the created usersid, email & name.
Now let’s update a User using,
UpdateUserMutation here is the resolve function of this.
As you can see we asked
id argument from mutation query and trying to find a user with that, later we update it.
In this mutation, we are updating user email with id 2.
In delete mutation, if you just pass id and you can delete a user.
And now query will be like this:
This call will delete the user with id 2 and return the deleted user id, name & email.
With that we have a complete CRUD operation in GraphQL, I will create Follow and Tweet queries and mutation and it will be available in GitHub repo.
Although GraphQL is very cool and defiantly going to replace REST in future but at the time writing of this post GraphQL is still a specification and not very well implemented in laravel community, the package we have used laravel-graphql is still a work in progress as of 15th Aug 2017, but I think the amount of flexibility GraphQL is providing its worth the time to learn it. I have not covered all the code for brevity but you can access it at GitHub. I would love to hear from you. In next part, I will be building a twitter like app in Vue.js with all the bells and whistles possible using this GraphQL API soon. As always if you like it please comment I love to hear your thoughts and feedback on it.