« How to build a GraphQL Server using Laravel - Part 2

August 14, 2019 • ☕️ 3 min read

LaravelGraphQLAPIs

asset 1


In the first part of this series, we looked at what GraphQL is, it’s advantages and even compared it with REST and SOAP. In this part of the series, we would setup a Laravel project, on top of which our GraphQL server would sit.

As mentioned in the previous article, this series is divided into 3 parts:

What we’ll be building

In this project we’ll be building an API for a micro blog with which users can write articles. Furthermore, we would restrict certain features or functionality to only authenticated users.

Prerequisites

To follow through this article, you’ll need the following installed on your machine:

Creating the Project

To begin, let’s create a new Laravel project via Composer by executing command below in our terminal:

1composer create-project --prefer-dist laravel/laravel laravel-graphql-blog

The command above tells Composer to create a Laravel project named laravel-graphql-blog.

The result is a new directory called laravel-graphql-blog inside the folder we ran the composer create command. Don’t worry if you are new to Laravel’s structure. You will learn the role of the most important directories and files as we build or you can head over to the official documentation here.

Just to make sure we have everything working, run the commands below in your terminal to boot up our server:

1cd laravel-graphql
2php artisan serve

To make sure everything runs well, open http://localhost:8000 in your browser and you should see Laravel’s default page.

Setting up our Database

Now, open the .env file (which resides in the project’s root) and configure the database parameters shown below accordingly to your development environment:

1DB_CONNECTION=mysql
2DB_HOST=127.0.0.1
3DB_PORT=3306
4DB_DATABASE=homestead
5DB_USERNAME=homestead
6DB_PASSWORD=secret

Note: The above assumes you have already created a MySQL database for this project.

Creating our Models and Migrations

Laravel by default ships with a user model and it’s migration file. We would want to include an api_token column to our User migration file for our api authentication therefore, let’s edit out this migration:

1// database/migrations/2014_10_12_000000_create_users_table.php
2
3<?php
4
5use Illuminate\Support\Facades\Schema;
6use Illuminate\Database\Schema\Blueprint;
7use Illuminate\Database\Migrations\Migration;
8
9class CreateUsersTable extends Migration
10{
11 /**
12 * Run the migrations.
13 *
14 * @return void
15 */
16 public function up()
17 {
18 Schema::create('users', function (Blueprint $table) {
19 $table->bigIncrements('id');
20 $table->string('name');
21 $table->string('email')->unique();
22 $table->timestamp('email_verified_at')->nullable();
23 $table->string('api_token', 80)->unique()->nullable()->default(null);
24 $table->string('password');
25 $table->rememberToken();
26 $table->timestamps();
27 });
28 }
29
30 /**
31 * Reverse the migrations.
32 *
33 * @return void
34 */
35 public function down()
36 {
37 Schema::dropIfExists('users');
38 }
39}

Voila! Now, let’s create an Article model and its corresponding migration file. To do that, run the command below in the terminal:

1php artisan make:model Article -m

The command above after creating the Article model, thanks to the -m flag, would create it’s associated migration script.

A migration script defines the table structure needed to persist data in a database.

The Article model is implemented in the Article.php file that you will find inside the app directory. In fact, the app directory contains the code representing the application’s domain.

Once that’s done, open the migration file that was generated and update it’s up method as below:

1// database/migrations/2019_08_08_000000_create_articles_table.php
2
3/**
4* Run the migrations.
5*
6* @return void
7*/
8public function up()
9{
10 Schema::create('articles', function (Blueprint $table) {
11 $table->bigIncrements('id');
12 $table->unsignedBigInteger('user_id');
13 $table->string('title');
14 $table->text('content');
15 $table->timestamps();
16
17 // User ID foreign Key
18 $table->foreign('user_id')->references('id')->on('users');
19 });
20}

In the above migration file, we added a foreign key pointing to the id on our users table as well as the title and content columns.

Note: The up method is used to add new tables, columns, or indexes to your database, while the down method should reverse the operations performed by the up method.

Now, let’s run the migration by executing the command below in the terminal:

1php artisan migrate

Define relationships between models

Next, let’s define the relationships between our models. Take note, we’ll be defining only the necessary parts of the relationships needed for the purpose of this tutorial.

To do so, let’s update our models by defining the necessary relationships starting with our User Model:

1// app/User.php
2
3<?php
4
5namespace App;
6
7use Illuminate\Notifications\Notifiable;
8use Illuminate\Contracts\Auth\MustVerifyEmail;
9use Illuminate\Foundation\Auth\User as Authenticatable;
10
11class User extends Authenticatable
12{
13 use Notifiable;
14
15 /**
16 * The attributes that are mass assignable.
17 *
18 * @var array
19 */
20 protected $fillable = [
21 'name', 'email', 'password',
22 ];
23
24 /**
25 * The attributes that should be hidden for arrays.
26 *
27 * @var array
28 */
29 protected $hidden = [
30 'password', 'remember_token',
31 ];
32
33 /**
34 * The attributes that should be cast to native types.
35 *
36 * @var array
37 */
38 protected $casts = [
39 'email_verified_at' => 'datetime',
40 ];
41
42 /**
43 * @return \Illuminate\Database\Eloquent\Relations\HasMany
44 */
45 public function articles()
46 {
47 return $this->hasMany(Article::class);
48 }
49}

The relationship between a User and an Article, will be a one-to-many relationship. That is, a user can write as many articles as they wish but
an article can only belong to one user.

Let’s define the inverse of the relationship on the Article model:

1// app/Article.php
2
3<?php
4
5namespace App;
6
7use Illuminate\Database\Eloquent\Model;
8
9class Article extends Model
10{
11 /**
12 * The attributes that are mass assignable.
13 *
14 * @var array
15 */
16 protected $fillable = [
17 'user_id', 'title', 'content'
18 ];
19
20 /**
21 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
22 */
23 public function user()
24 {
25 return $this->belongsTo(User::class);
26 }
27}

One may ask, how is the Article model defined in app/Article.php linked to the articles table in our database. This happens because, by convention, Eloquent maps a model to a table having the same lowercase name in the plural.

Setting Database seeders

To test the API we are about to create, we need to have some data to work with. To do this, let’s create a database seeder to populate the tasks table with some data. We’ll start by creating some seeder classes for our users table. To do that, let’s run the command below in the terminal:

1php artisan make:seeder UsersTableSeeder

Seeders are classes that populate database tables with some data.

The command above will generate a new file called UsersTableSeeder.php file in database/seeds directory. Now let’s update it with with the following:

1// database/seeds/UsersTableSeeder.php
2
3<?php
4
5use App\User;
6use App\Article;
7use Illuminate\Database\Seeder;
8
9class UsersTableSeeder extends Seeder
10{
11 /**
12 * Run the database seeds.
13 *
14 * @return void
15 */
16 public function run()
17 {
18 $faker = \Faker\Factory::create();
19
20 User::create([
21 'name' => $faker->name,
22 'email' => 'me@mygraphqlapp.com',
23 'password' => bcrypt('secret')
24 ]);
25
26 factory(User::class, 50)->create()->each(function($user) use ($faker){
27 for ($i=0; $i < 5; $i++) {
28 Article::create([
29 'user_id' => $user->id,
30 'title' => $faker->sentence,
31 'content' => $faker->paragraphs(3,true),
32 ]);
33 }
34 });
35 }
36}

In the above code, our UsersTableSeeder would first create a User with a random name but with an email of me@mygraphqlapp.com and password of secret.

Furthermore, using our default User factories which is located in the database/factories directory, we create 50 dummy users and for each one of these 50 users, 5 dummy articles are created under them.

To run our UsersTableSeeder let’s update our DatabaseSeeder.php file database/seeds directory with the code below;

1// database/seeds/UsersTableSeeder.php
2
3<?php
4
5use Illuminate\Database\Seeder;
6
7class DatabaseSeeder extends Seeder
8{
9 /**
10 * Seed the application's database.
11 *
12 * @return void
13 */
14 public function run()
15 {
16 $this->call(UsersTableSeeder::class);
17 }
18}

Finally, let’s go ahead and run our database seeders to get some data into our database by running the command below in the terminal:

1php artisan db:seed

Conclusion

That’s all for this part of the series. In this article, we’ve learn’t how to setup a Laravel project and created a micro blog. We’ve only setup up our Laravel project and in the next part of the series, which is the last part, we would be building out our GraphQL API.

Feel free to hit me up with your views, comments or questions. Stay tuned!