Solomon Antoine
Posted on January 16, 2022
Get Started with GraphQL and Laravel
GraphQL is a powerful REST alternative that allows developers to build APIs. We will be using GraphQL to create a simple CRUD application that allows us to create, read, update and delete data.
Setup the project
Prerequisites
Create new Laravel Project
Use composer to create a new Laravel project by running:
composer create-project --prefer-dist laravel/laravel graphql-basics
Install Laravel Sail
We will be using Laravel Sail to run our local environment. Sail allows us to seamlessly run Docker without complex configuration
composer require laravel/sail --dev
php artisan sail:install
Select [0]
the mysql service
Start Docker
Create a sail shortcut:
alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
Start Sail & Docker:
sail up -d
Install GraphQL Laravel library
The most popular GraphQL libraries for Laravel are Rebing & Lighthouse, in our tutorial we will be using Rebing
which we can install by running:
composer require rebing/graphql-laravel
Then publish the config file
sail artisan vendor:publish --provider="Rebing\\GraphQL\\GraphQLServiceProvider"
Prepare database migrations & models
Run the following command to create the Company model, migration and factory:
sail artisan make:model Company -m -f
Migration
Edit the generated migration file by replacing its content with the following:
<?php
use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;
class CreateCompaniesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('companies', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('contact_email');
$table->string('street_address');
$table->string('city');
$table->string('country');
$table->string('domain');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('companies');
}
}
Model
Now, add these fields as $fillable
properties for the Company model.
<?php
namespace App\\Models;
use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
use Illuminate\\Database\\Eloquent\\Model;
class Company extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var string[]
*/
protected $fillable = [
'name',
'contact_email',
'street_address',
'city',
'country',
'domain'
];
}
Factory
Let's create our Company factory for seeding purposes.
<?php
namespace Database\\Factories;
use Illuminate\\Database\\Eloquent\\Factories\\Factory;
class CompanyFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'name' => $this->faker->company,
'contact_email' => $this->faker->companyEmail,
'street_address' => $this->faker->streetAddress,
'city' => $this->faker->city,
'country' => $this->faker->country,
'domain' => $this->faker->domainName
];
}
}
Update Database Seeder
<?php
namespace Database\\Seeders;
use App\\Models\\Company;
use Illuminate\\Database\\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
Company::factory(10)->create();
}
}
Migrate & Seed Database
Run this command to seed our database:
sail artisan migrate --seed
Build our GraphQL Server
Let's start defining our GraphQL schema
Create GraphQL Type for Company
Run the following command to create our GraphQL type:
sail artisan make:graphql:type CompanyType
Then navigate to the app/GraphQL/Types
directory and modify the file like so:
<?php
declare(strict_types=1);
namespace App\\GraphQL\\Types;
use App\\Models\\Company;
use GraphQL\\Type\\Definition\\Type;
use Rebing\\GraphQL\\Support\\Type as GraphQLType;
class CompanyType extends GraphQLType
{
protected $attributes = [
'name' => 'Company',
'description' => '',
'model' => Company::class
];
public function fields(): array
{
return [
'id' => [
'type' => Type::id(),
'description' => 'The auto incremented ID of a company'
],
'name' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The name of a company'
],
'contact_email' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The primary point of contact for a company'
],
'street_address' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The street address of a company headquarters'
],
'city' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The city of a company headquarters'
],
'country' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The country of a company headquarters'
],
'domain' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The web domain for a company'
]
];
}
}
Create GraphQL Queries
Queries will be used to retrieve data from the database.
CompanyQuery
Run the following to create the company query:
sail artisan make:graphql:query CompanyQuery
Then navigate to the app/GraphQL/Queries
directory and modify the file like so:
<?php
declare(strict_types=1);
namespace App\\GraphQL\\Queries;
use App\\Models\\Company;
use Closure;
use GraphQL\\Type\\Definition\\ResolveInfo;
use GraphQL\\Type\\Definition\\Type;
use Rebing\\GraphQL\\Support\\Facades\\GraphQL;
use Rebing\\GraphQL\\Support\\Query;
use Rebing\\GraphQL\\Support\\SelectFields;
class CompanyQuery extends Query
{
protected $attributes = [
'name' => 'company'
];
public function type(): Type
{
return GraphQL::type('Company');
}
public function args(): array
{
return [
'id' => [
'name' => 'id',
'type' => Type::id(),
'rules' => ['required']
],
];
}
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, Closure $getSelectFields)
{
return Company::findOrFail($args['id']);
}
}
CompaniesQuery
Run the following to create the companies query:
sail artisan make:graphql:query CompaniesQuery
Then navigate to the app/GraphQL/Queries
directory and modify the file like so:
<?php
declare(strict_types=1);
namespace App\\GraphQL\\Queries;
use App\\Models\\Company;
use Closure;
use GraphQL\\Type\\Definition\\ResolveInfo;
use GraphQL\\Type\\Definition\\Type;
use Rebing\\GraphQL\\Support\\Facades\\GraphQL;
use Rebing\\GraphQL\\Support\\Query;
use Rebing\\GraphQL\\Support\\SelectFields;
class CompaniesQuery extends Query
{
protected $attributes = [
'name' => 'companies'
];
public function type(): Type
{
return Type::listOf(GraphQL::type('Company'));
}
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, Closure $getSelectFields)
{
return Company::all();
}
}
Create the GraphQL Mutations
Mutations are used insert, update, and delete an entity.
Create Company Mutation
Run the following command to create new mutation:
sail artisan make:graphql:mutation CreateCompanyMutatio
Then navigate to the app/GraphQL/Mutations
directory and modify the file like so:
<?php
declare(strict_types=1);
namespace App\\GraphQL\\Mutations;
use App\\Models\\Company;
use Closure;
use GraphQL\\Type\\Definition\\ResolveInfo;
use GraphQL\\Type\\Definition\\Type;
use Rebing\\GraphQL\\Support\\Facades\\GraphQL;
use Rebing\\GraphQL\\Support\\Mutation;
use Rebing\\GraphQL\\Support\\SelectFields;
class CreateCompanyMutation extends Mutation
{
protected $attributes = [
'name' => 'createCompany'
];
public function type(): Type
{
return GraphQL::type('Company');
}
public function args(): array
{
return [
'name' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The name of a company'
],
'contact_email' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The primary point of contact for a company',
'rules' => ['email']
],
'street_address' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The street address of a company headquarters'
],
'city' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The city of a company headquarters'
],
'country' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The country of a company headquarters'
],
'domain' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The web domain for a company'
]
];
}
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, Closure $getSelectFields)
{
return Company::create($args);
}
}
Update Company Mutation
Run the following command to create new mutation:
sail artisan make:graphql:mutation UpdateCompanyMutation
Then navigate to the app/GraphQL/Mutations
directory and modify the file like so:
<?php
declare(strict_types=1);
namespace App\\GraphQL\\Mutations;
use App\\Models\\Company;
use Closure;
use GraphQL\\Type\\Definition\\ResolveInfo;
use GraphQL\\Type\\Definition\\Type;
use Rebing\\GraphQL\\Support\\Facades\\GraphQL;
use Rebing\\GraphQL\\Support\\Mutation;
use Rebing\\GraphQL\\Support\\SelectFields;
class UpdateCompanyMutation extends Mutation
{
protected $attributes = [
'name' => 'updateCompany'
];
public function type(): Type
{
return GraphQL::type('Company');
}
public function args(): array
{
return [
'id' => [
'name' => 'id',
'type' => Type::nonNull(Type::int()),
],
'name' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The name of a company'
],
'contact_email' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The primary point of contact for a company',
'rules' => ['email']
],
'street_address' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The street address of a company headquarters'
],
'city' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The city of a company headquarters'
],
'country' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The country of a company headquarters'
],
'domain' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The web domain for a company'
]
];
}
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, Closure $getSelectFields)
{
$company = Company::findOrFail($args['id']);
$company->update($args);
return $company->refresh();
}
}
Delete Company Mutation
Run the following command to create new mutation:
sail artisan make:graphql:mutation DeleteCompanyMutation
Then navigate to the app/GraphQL/Mutations
directory and modify the file like so:
<?php
declare(strict_types=1);
namespace App\\GraphQL\\Mutations;
use App\\Models\\Company;
use Closure;
use GraphQL\\Type\\Definition\\ResolveInfo;
use GraphQL\\Type\\Definition\\Type;
use Rebing\\GraphQL\\Support\\Mutation;
use Rebing\\GraphQL\\Support\\SelectFields;
class DeleteCompanyMutation extends Mutation
{
protected $attributes = [
'name' => 'deleteCompany'
];
public function type(): Type
{
return Type::boolean();
}
public function args(): array
{
return [
'id' => [
'name' => 'id',
'type' => Type::id(),
],
];
}
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, Closure $getSelectFields)
{
$company = Company::findOrFail($args['id']);
return $company->delete();
}
}
Load Schema
We need to register to schema within the GraphQL configuration file, located at config/graphql.php
:
'schemas' => [
'default' => [
'query' => [
// ExampleQuery::class,
\\App\\GraphQL\\Queries\\CompanyQuery::class,
\\App\\GraphQL\\Queries\\CompaniesQuery::class
],
'mutation' => [
// ExampleMutation::class,
\\App\\GraphQL\\Mutations\\CreateCompanyMutation::class,
\\App\\GraphQL\\Mutations\\UpdateCompanyMutation::class,
\\App\\GraphQL\\Mutations\\DeleteCompanyMutation::class
],
// The types only available in this schema
'types' => [
\\App\\GraphQL\\Types\\CompanyType::class
],
// Laravel HTTP middleware
'middleware' => null,
// Which HTTP methods to support; must be given in UPPERCASE!
'method' => ['GET', 'POST'],
// An array of middlewares, overrides the global ones
'execution_middleware' => null,
],
],
Run the Application
Since we already started the app using Sail, we can go to the url: http://localhost/graphiql to test our endpoints
Return all companies
{
companies {
id
name
contact_email
street_address
city
country
domain
}
}
Return single company
{
company(id:1) {
id
name
contact_email
street_address
city
country
domain
}
}
Create company
mutation {
createCompany(name:"Apple Inc.", contact_email:"support@apple.com",
street_address:"One Apple Park Way", city: "Cupertino", country:"USA", domain:"apple.com") {
name
domain
}
}
Update Company
mutation {
updateCompany(id: 3, name: "Facebook Inc.", contact_email: "support@facebook.com",
street_address:"1 Hacker Way, Menlo Park", city: "Menlo Park", country: "USA",
domain: "facebook.com") {
name
domain
}
}
Delete Company
mutation {
deleteCompany(id: 7)
}
Recap
In conclusion, GraphQL is a very powerful tool for building modern APIs. If you found this tutorial useful, considering subscribing to my YouTube channel where I record
programming content on the regular.
Social
Posted on January 16, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.