Developing and Securing GraphQL APIs with Laravel

Developing and Securing GraphQL APIs with Laravel

This article will show you how to use Laravel to implement a basic GraphQL API and how to secure it with Auth0. Throughout the article, you will learn how to implement the API step by step up to the final result.

This article will show you how to use Laravel to implement a basic GraphQL API and how to secure it with Auth0. Throughout the article, you will learn how to implement the API step by step up to the final result.

Learn how to develop GraphQL APIs with Laravel and how to secure them with Auth0. You can find the final code on this GitHub repository.

The API You Will Build

The project you are going to build is an API providing a list of wines from all over the world. As mentioned before, you will build the API following the GraphQL model. This model allows a client to request the exact data it needs, nothing more, nothing less. 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.

Before starting the project, ensure you have PHP and MySQL installed on your machine. You will also need Composer, a dependency manager for PHP.

Once you have these tools installed on your machine, you are ready to build the Wine Store API.

Setting up the Laravel PHP Project

The first step to create a Laravel project is to run the following command in a terminal:

composer create-project --prefer-dist laravel/laravel winestore


This command asks Composer to create a Laravel project named winestore. The result is a new directory called winestore right where you ran the command. This directory will have a few files and subdirectories as shown in the following picture:

Don’t worry if you are not acquainted with Laravel’s structure. While you will build the application, you will learn the role of the most important directories and files.

Creating the Wine Store Model

Now you can start to modify the scaffolded project to implement the Wine Store data model.

Creating the Model and the Migration Script

For starters, you will need to use your terminal to move into the winestore project. After that you will run the following command:

# make sure you run it from the winestore directory
php artisan make:model Wine -m


This command will create the Wine model and, thanks to the -m flag, a migration script for database persistence.

The Wine model is implemented in the Wine.php file that you will find inside the app directory. In fact, the app directory contains the code representing the application’s domain. The content of the Wine.php file will be as follows:

// ./app/Wine.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Wine extends Model
{
    //
}


As you can see, this file defines an empty class extending the Model class from Eloquent. Eloquent is the Object-Relational Mapping (ORM) library shipped with Laravel.

The make:model command you ran a few moments ago also generated a migration script that defines the table structure needed to persist wines in a database. You will find this migration script in the database/migrations directory. If you open this directory, you will find three files whose name starts with a timestamp.

Laravel generated the first two files while initializing the project. These files and are related to the built-in user management feature provided by Laravel. The last file, ending with _create_wines_table.php, is the migration script for the Wine model. Migration scripts are used by Eloquent to create or update the schema of the tables in the application’s database. The timestamp prefix for each file helps Eloquent identify which migrations it needs to apply and in which order.

Now, open the file ending with _create_wines_table.php and put the following code inside it:

//database/migrations/yyyy_mm_dd_hhMMss_create_wines_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateWinesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('wines', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 50);
            $table->text('description');
            $table->string('color', 10);
            $table->string('grape_variety', 50);
            $table->string('country', 50);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('wines');
    }
}


Note: The up() is executed when an upgrade is applied to the database and the down() method is executed when a downgrade is applied.
As you can see, the code you inserted in this file is defining a few columns in your database (like name, description, and country). These columns will help you persist, in the database, the details of the wines.

Add Seeders to the Database

To test the API you are about to create, you need to feed some initial data to your database. To do this, you can create a seeder. Seeders are classes that populate database tables. To create a seeder, type the following command:

# from the winestore directory
php artisan make:seeder WinesTableSeeder


This command will generate a new file called WineTableSeeder.php file in the database/seeds directory. Open this file and change its content with the following one:

// ./database/seeds/WinesTableSeeder.php

<?php

use App\Wine;
use Illuminate\Database\Seeder;

class WinesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Wine::create([
            'name' => 'Classic Chianti',
            'description' => 'A medium-bodied wine characterized by a marvelous freshness with a lingering, fruity finish',
            'color' => 'red',
            'grape_variety' => 'Sangiovese',
            'country' => 'Italy'
        ]);

        Wine::create([
            'name' => 'Bordeaux',
            'description' => 'A wine with fruit scents and flavors of blackberry, dark cherry, vanilla, coffee bean, and licorice. The wines are often concentrated, powerful, firm and tannic',
            'color' => 'red',
            'grape_variety' => 'Merlot',
            'country' => 'France'
        ]);

        Wine::create([
            'name' => 'White Zinfandel',
            'description' => 'Often abbreviated as White Zin, it is a dry to sweet wine, pink-colored rosé',
            'color' => 'rosé',
            'grape_variety' => 'Zinfandel',
            'country' => 'USA'
        ]);

        Wine::create([
            'name' => 'Port',
            'description' => 'A fortified sweet red wine, often served as a dessert wine',
            'color' => 'red',
            'grape_variety' => 'Touriga Nacional',
            'country' => 'Portugal'
        ]);

        Wine::create([
            'name' => 'Prosecco',
            'description' => 'It is a dry white wine (brut) sometimes with a sweet flavor of green apple, honeydew melon, pear, and honeysuckle',
            'color' => 'white',
            'grape_variety' => 'Glera',
            'country' => 'Italy'
        ]);
    }
}


The run() method of the WinesTableSeeder class creates instances of the Wine model based on the specified values. Now, edit the DatabaseSeeder.php file you find in the same folder and invoke the WinesTableSeeder class inside the run() method. The following is the resulting code:

//database/seeds/DatabaseSeeder.php
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $this->call(WinesTableSeeder::class);
    }
}


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

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret


Note: The up() is executed when an upgrade is applied to the database and the down() method is executed when a downgrade is applied.

docker run --name mysql \
   -p 3306:3306 \
   -e MYSQL_ROOT_PASSWORD=myextremellysecretpassword \
   -e MYSQL_DATABASE=homestead \
   -e MYSQL_USER=homestead \
   -e MYSQL_PASSWORD=secret \
   -d mysql:5.7


After this preparation, you are ready to create the table schema and to populate it. Type the following in a console window:

php artisan migrate:fresh --seed


This command will clear the database, execute the migration scripts, and run the database seeder.

Note: The up() is executed when an upgrade is applied to the database and the down() method is executed when a downgrade is applied.## Introducing GraphQL

So far, you defined the model and its database persistence. Now you can build the GraphQL API upon that.

Why GraphQL

The API you are going to implement is based on GraphQL, a specification from Facebook defining a query language for APIs. With respect to classic REST APIs, GraphQL allows you to define a single endpoint providing multiple resources to the clients. This contributes to reduce network traffic and to potentially speed up client applications. In addition, GraphQL allows a client to request just the data it needs, avoiding to receive a resource with all possible information. Again, this reduces the network traffic and optimizes the data processing on the client side.

GraphQL achieves this result by defining an abstract language to describe queries, schemas, and types, in a similar way as in a database. As said before, GraphQL is a specification. This means that GraphQL is independent of any programming language. If you want to use it in your application, you need to choose among the several available implementations available in almost any language.

Installing the GraphQL Library

To support GraphQL in the application you’re going to build you need to install a library that allows you to define schemas and queries in a simple way. The Laravel GraphQL library is one of the best for this purpose. To install it, issue the following command from the project root:

# issue this from the winestore directory:
composer require rebing/graphql-laravel


After the installation, you need to run the following command:

php artisan vendor:publish --provider="Rebing\GraphQL\GraphQLServiceProvider"


This command extracts the graphql.php configuration file from the vendor folder and put it into the config folder. This is a common approach that allows you to get one or more configuration files from a third party package so that you can change it for the needs of your application. You will use the graphql.php file later.

Creating the GraphQL API Schema

Since GraphQL is a query language, you need to know how you can build your query, what type of object you can receive as a response, and what fields you can request from the server. A GraphQL API endpoint provides a complete description of what your client can query. This description is called schema, a collection of data defining the queries that a client can request, the type of the returned resources, the allowed change requests to the resources, also known as mutations, and others.

To keep things simple, your API will allow you to retrieve the list of wines in the Wine Store and a specific wine. So its schema will consist of queries and types.

Creating the Wine Type

You will start by creating the API’s schema by defining the resource returned. To do this, create the GraphQL directory inside the app directory. This directory will contain all the definitions you need for the GraphQL schema of the API. In the app/GraphQL directory, create the Types directory and put in it a file called WineType.php with the following content:

// ./app/GraphQL/Types/WineType.php
<?php

namespace App\GraphQL\Types;

use App\Wine;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Type as GraphQLType;

class WineType extends GraphQLType
{
    protected $attributes = [
        'name' => 'Wine',
        'description' => 'Details about a wine',
        'model' => Wine::class
    ];

    public function fields()
    {
        return [
            'id' => [
                'type' => Type::nonNull(Type::int()),
                'description' => 'Id of the wine',
            ],
            'name' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The name of the wine',
            ],
            'description' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'Short description of the wine',
            ],
            'color' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The color of the wine',
            ],
            'grape_variety' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The grape variety of the wine',
            ],
            'country' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The country of origin of the wine',
            ]
        ];
    }
}


This file defines the WineType class by extending GraphQLType. Notice the definition of three protected attributes that assign the name of the type (Wine), a description (“Details about a wine”), and the model the type is associated with (the Wine class you defined before). The fields() method returns an array with the property definitions of the resources your API will expose.

Creating the GraphQL Queries

Now, create a Queries directory inside the ./app/GraphQL directory and put there a file called WinesQuery.php with the following content:

// ./app/GraphQL/Queries/WinesQuery.php

<?php

namespace App\GraphQL\Queries;

use App\Wine;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Query;

class WinesQuery extends Query
{
    protected $attributes = [
        'name' => 'wines',
    ];

    public function type()
    {
        return Type::listOf(GraphQL::type('Wine'));
    }

    public function resolve($root, $args)
    {
        return Wine::all();
    }
}


The WinesQuery class defined in this file represents a query that returns the list of wines from the Wine Store. You see that the query’s name is wines. The type() method returns the type of the resource returned by the query, expressed as a list of Wine type items. The resolve() method actually returns the list of wines by using the all() method of the Wine model.

In the same way, create a second file in the ./app/GraphQL/Queries directory called WineQuery.php (note that, this time, wine is singular). In this file, add the following code:

// ./app/GraphQL/Queries/WineQuery.php

<?php

namespace App\GraphQL\Queries;

use App\Wine;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Query;

class WineQuery extends Query
{
    protected $attributes = [
        'name' => 'wine',
    ];

    public function type()
    {
        return GraphQL::type('Wine');
    }

    public function args()
    {
        return [
            'id' => [
                'name' => 'id',
                'type' => Type::int(),
                'rules' => ['required']
            ],
        ];
    }

    public function resolve($root, $args)
    {
        return Wine::findOrFail($args['id']);
    }
}


In this case, the WineQuery.php file contains the definition of the query returning a single wine identified by the id field. Notice that the definition of the id argument specifies that the argument must be an integer and that it is mandatory (required). You should be able to read the meaning of the other members of the WineQuery class: the query’s name is wine, the returned type is Wine, and the returned resource is the wine identified by the id field.

Registering the Schema

After creating these types and queries, you need to register these items as the GraphQL schema in your API. So, open the graphql.php file (you will find it inside the config directory) and replace the current definition of 'schemas' with the following:

// ./config/graphql.php

// ...
    'schemas' => [
        'default' => [
            'query' => [
                'wine' => App\GraphQL\Queries\WineQuery::class,
                'wines' => App\GraphQL\Queries\WinesQuery::class,
            ]
        ],
    ],
// ...


Here you are saying that the schema of your GraphQL API consists of two queries named wine and wines, mapped to WineQuery and WinesQuery classes respectively.

Then, in the same file, replace the current definition of 'types' with the following:

// ./config/graphql.php

// ...
    'types' => [
      'Wine' => App\GraphQL\Types\WineType::class,
  ],
// ...


This definition maps the type GraphQL Wine to the WineType class.

Testing the API with GraphiQL

At this point, you are ready to use your GraphQL API. You could test the API by using [curl](https://curl.haxx.se/ "curl"), Postman, or any other HTTP client. But a specialized client can help you to better appreciate the power and the flexibility of GraphQL. One client that you can use is Electron GraphiQL, which is available for Windows, Linux, and Mac.

To use it, head to the GraphiQL homepage and download the version available for your operating system. After downloading and installing it, open the tool and change the GraphQL endpoint to [http://localhost:8000/graphql](http://localhost:8000/graphql "http://localhost:8000/graphql"). Right now, as you are not running your project yet, you will see a message saying Error: connect ECONNREFUSED 127.0.0.1:8000 on the right-hand side of the tool.

To fix that, head back to your terminal and issue the following commands:

# create the tables needed to persist wine
php artisan migrate

# seed the database with the test data
php artisan db:seed

# run the server
php artisan serve


As described in the comments above, the first two commands will create the database schema and seed it with the test data. Then, the last command will make your Laravel project run.

Now, back to the GraphiQL tool, paste the following query and press the play button (or you can hit Control + Enter to issue the query):

{
  wines {
    name, color
    }
}


The expression above specifies the name of the query (wines) and the fields of the resource you are interested in (name and color). The response to this request is a JSON object containing an array of wines with the requested fields only. You can try adding another field, like id or description, and issuing the query again to see what happens.

Securing Your Laravel and GraphQL API with Auth0

Now that you have a working GraphQL API, you probably want to restrict the access to it so that only authorized clients can consume it. One easy way to secure your API is to integrate it with Auth0. In this article, you will create an Auth0 API to represent your GraphQL and Laravel API, then you will configure a GraphiQL tool to issue authenticated requests to it. If you are developing a client application, you will need to learn how to integrate them with Auth0 to be able to consume your API. The way you integrate a client application with Auth0 depends on what type of client you are developing. Check Auth0’s docs to learn more.

Securing the API

The first step is to sign up for a free Auth0 account, if you don’t have one yet. Then, from your Auth0 dashboard, head to the APIs section, click on the Create API button, and fill the form as follows:

  • Name: “Laravel and GraphQL API”
  • Identifier: [https://laravel-graphql-api](https://laravel-graphql-api "https://laravel-graphql-api")
  • Signing Algorithm: RS256

Note: The up() is executed when an upgrade is applied to the database and the down() method is executed when a downgrade is applied.
After clicking on the Create button on this form, Auth0 will redirect you to the Quick Start section of your new API. From there, head to the Applications section of your dashboard and choose the “Laravel and GraphQL API (Test Application)” that Auth0 created for you. After clicking on it, Auth0 will show you a screen where you will see some properties of this application. Leave this page open and head back to your project.

Back in your project, open the .env file (you will find it in the project root) and add the following properties to it:

AUTH0_DOMAIN=https://<YOUR_DOMAIN>/
AUTH0_AUDIENCE=<YOUR_AUDIENCE>


You will have to replace <YOUR_DOMAIN> and <YOUR_AUDIENCE> with the properties from your Auth0 account. More specifically, you will have to replace the first placeholder with the Domain property of your Auth0 Application (e.g., blog-samples.auth0.com), and you will have to replace <YOUR_AUDIENCE> with your Auth0 API identifier (i.e., with [https://laravel-graphql-api](https://laravel-graphql-api "https://laravel-graphql-api")).

Now, you will have to create a middleware in your Laravel application to check if the HTTP requests sent to the API are authorized (i.e., if they contain valid access tokens). You can create a middleware by running the following command (you will need to stop the Laravel server by issuing Control + C first):

php artisan make:middleware CheckAccess


Issuing this command will create a new file called CheckAccess.php inside the ./app/Http/Middleware directory. Before changing this file, you will have to install the Auth0 PHP SDK:

composer require auth0/auth0-php


After installing this SDK, replace the contents of the ./app/Http/Middleware/CheckAccess.php file with this:

// ./app/Http/Middleware/CheckAccess.php

<?php

namespace App\Http\Middleware;

use Closure;
use Auth0\SDK\JWTVerifier;

class CheckAccess
{
    public function handle($request, Closure $next)
    {
        if (!empty(env('AUTH0_AUDIENCE')) && !empty(env('AUTH0_DOMAIN'))) {
            $verifier = new JWTVerifier([
                'valid_audiences' => [env('AUTH0_AUDIENCE')],
                'authorized_iss' => [env('AUTH0_DOMAIN')],
                'supported_algs' => ['RS256']
            ]);
            $token = $request->bearerToken();
            $decodedToken = $verifier->verifyAndDecode($token);
            if (!$decodedToken) {
                abort(403, 'Access denied');
            }
        }
        return $next($request);
    }
}


The handle() method of the CheckAccess middleware checks the access token only if you have configured your application by providing an Auth0 audience and domain (otherwise, it simply allows all requests). If that is the case, this method creates an instance of the JWTVerifier class based on the Auth0 configuration data you set in the .env file. Then this method retrieves the current bearer token from the HTTP request and verifies the JWTVerifier instance.

If the token is valid, the request is forwarded to GraphQL. Otherwise, an Access denied message is sent back.

Note: The up() is executed when an upgrade is applied to the database and the down() method is executed when a downgrade is applied.

RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]


Once you have defined this middleware, you need to register it. To do this, open the ./app/Http/Kernel.php file and add, to the $routeMiddleware list, a mapping between a key (checkAccess) and the newly created middleware class (CheckAccess):

// ./app/Http/Kernel.php

protected $routeMiddleware = [
  // ... other mappings ...
  'checkAccess' => \App\Http\Middleware\CheckAccess::class,
];


As a final step, associate the CheckAccess middleware to the GraphQL schema by changing the ./config/graphql.php file as follows:

// ./config/graphql.php

// ...
'schemas' => [
    'default' => [
        'query' => [
            'wine' => App\GraphQL\Queries\WineQuery::class,
            'wines' => App\GraphQL\Queries\WinesQuery::class,
        ],
        'middleware' => ['checkAccess']
    ],
],
// ...


The middleware declaration asserts that Laravel will execute the checkAccess middleware for each request to the GraphQL schema. With that in place, you have finished securing your Laravel and GraphQL API with Auth0. To confirm that everything is in order, try using the GraphiQL tool to issue the same request as before (you will need to restart the server by issuing php artisan serve). If your configuration works, you will get an error.

Authorizing the GraphiQL Client

To be able to fetch your GraphQL API again, you will need to issue, from the GraphiQL client, requests with access tokens. As mentioned before, the way you get an access token varies depending on what type of client you are developing. However, in this article, for testing purposes, you will use a test token.

To get this token, open the APIs section in your Auth0 dashboard, then click on the API you created (“Laravel and GraphQL API”). Now, click on the Test tab then, if you scroll down a little bit, you will see a button called Copy Token. Click on this button to get a copy of the access token in your clipboard.

Now, head back to the GraphiQL tool, click on the blue Edit HTTP Headers button, click on the Add Header button, then add the following header:

  • Name: “Laravel and GraphQL API”
  • Identifier: [https://laravel-graphql-api](https://laravel-graphql-api "https://laravel-graphql-api")
  • Signing Algorithm: RS256

Make sure you use the access token you copied from your Auth0 dashboard (instead of eyJ...aEw), then hit save.

Now, click outside the dialog where you added the header, then hit the play button (or hit Control + Enter). If everything works as expected, you will see that you can fetch the list of wines again.

Summary

In this article, you learned how to create GraphQL APIs with Laravel and how to secure them with Auth0.

You started by creating a model with its migration scripts to persist data in a database. Besides that, you created a seeder for the model to populate the database with some initial test data. Then you continued to build your API by defining a GraphQL type and two GraphQL queries. After that, you used the GraphiQL browser-based client to test the GraphQL API interactively.

Finally, you used Auth0 to secure the GraphQL and to authorize the GraphQL client. What do you think about the process as a whole? Let us know on the comments box below.

Laravel API Response - Simple Laravel API response wrapper

Laravel API Response - Simple Laravel API response wrapper

Laravel API Response is a good package that we can use to create API responses easily.

Simple and ready to use API response wrapper for Laravel - Simple Laravel API response wrapper.

Installation
  1. Install package through composer: $ composer require obiefy/api-response
  2. publish config file : php artisan vendor:publish --tag=api-response
Basic usage

Create and return JSON response:

use Obiefy\API\Facades\API;
...
public function index()
{
    $users = User::all();
return API::response(200,'users list', $users);

}

Or you can use helper function:

use Obiefy\API\Facades\API;
...
public function index()
{
$users = User::all();

return api()-&gt;response(200, 'users list', $users);

}

Advanced usage

1. General example

use Obiefy\API\Facades\API;
...
public function index()
{
$users = User::all();

return API::response(200, 'users list', $users);

}

result:

{
"STATUS": 200,
"MESSAGE": "users list",
"DATA": [
{"name": "user name"}
]
}

2. Success response

return api()->ok('Success message`, [
'name' => 'Obay Hamed'
]);

result:

{
"STATUS": 200,
"MESSAGE": "Success message",
"DATA": {"name": "Obay Hamed"}
}

you can also return success message with out passing parametters

return api()->ok();

in this case response message will be the default message from config file config('api.messages.success') the same thing for api()->notFound() and api()->validation().

Source Code: https://github.com/obiefy/api-response

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow me on Facebook | Twitter

Further reading

Laravel 5.8 Tutorial for Beginners

Tutorial Laravel 6 with Docker and Docker-Compose

How to Laravel 6 Database Migrations - Add Admin Role to Users

Laravel 6 Release New Features and Upgrade

Laravel 6 CRUD Application Tutorial


Building a GraphQL Server with Laravel

Building a GraphQL Server with Laravel

Building a GraphQL Server with Laravel - In this post we'll build out a GraphQL server in Laravel, and then in a following post, we'll build a client app which uses our new server to display some data.

Building a GraphQL Server with Laravel - In this post we'll build out a GraphQL server in Laravel, and then in a following post, we'll build a client app which uses our new server to display some data.

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.

Project Overview

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.

Project Resources

Our application will consist of two resources: Articles and Users. These resources will be defined as object types in our GraphQL schema:

type User {
  id: ID!
  name: String!
  email: String!
  articles: [Article!]!
}

type Article {
  id: ID!
  title: String!
  content: String!
  author: User!
}

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:

type Query {
user(id: ID!): User
  users: [User!]!

  article(id: ID!): Article
  articles: [Article!]!
}

type Mutation {
  createUser(name: String!, email: String!, password: String!): User
  createArticle(title: String!, content: String!): Article
}

Setting Up Our Laravel Project

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:

$ composer create-project --prefer-dist laravel/laravel laravel-graphql

Just to make sure we have everything working, let’s boot up our server and make sure we see Laravel’s default page:

$ cd laravel-graphql
$ php artisan serve
Laravel development server started: <http://127.0.0.1:8000>

Database Models and Migrations

For the purposes of this article, we will be using SQLite. So, let’s make the following changes to the default .env file:

DB_CONNECTION=sqlite
# DB_HOST=
# DB_PORT=
# DB_DATABASE=database.sqlite
# DB_USERNAME=
# DB_PASSWORD=

Next, let’s create our database file:

$ touch ./database/database.sqlite

Laravel ships with a user model and some basic migration files. Let’s quickly add an api_tokencolumn to our in our CreateUsersTable migration file provided to us by Laravel:

/database/migrations/XXXX_XX_XX_000000_create_users_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->string('api_token', 80)->unique()->nullable()->default(null);
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

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:

$ php artisan make:model Article -m

Note: The -m option creates a migration file for our newly created article model.

Let’s make some adjustments to the generated migration file:

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
            $table->string('title');
            $table->text('content');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }
}

We’ve added a foreign key pointing to the id on our users table as well as the title and 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:

$ php artisan migrate

Next, let’s update our models by defining the necessary relationships:

app/User.php
namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    // ...

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function articles()
    {
        return $this->hasMany(Article::class);
    }
}

app/Article.php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'title', 'content',
    ];

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Database Seeding

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 articles and users tables:

$ php artisan make:seeder UsersTableSeeder 
$ php artisan make:seeder ArticlesTableSeeder

Next, let’s set them up to insert some dummy data into our SQLite database:

database/seeds/UsersTableSeeder.php
use App\User;
use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run()
    {
        \App\User::truncate();

        $faker = \Faker\Factory::create();
        $password = bcrypt('secret');

        \App\User::create([
            'name'     => $faker->name,
            'email'    => '[email protected]',
            'password' => $password,
        ]);

        for ($i = 0; $i < 10; ++$i) {
            \App\User::create([
                'name'     => $faker->name,
                'email'    => $faker->email,
                'password' => $password,
            ]);
        }
    }
}

database/seeds/ArticlesTableSeeder.php
use App\Article;
use Illuminate\Database\Seeder;

class ArticlesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run()
    {
        \App\Article::truncate();
        \App\Article::unguard();

        $faker = \Faker\Factory::create();

        \App\User::all()->each(function ($user) use ($faker) {
            foreach (range(1, 5) as $i) {
                \App\Article::create([
                    'user_id' => $user->id,
                    'title'   => $faker->sentence,
                    'content' => $faker->paragraphs(3, true),
                ]);
            }
        });
    }
}

/database/seeds/DatabaseSeeder.php
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UsersTableSeeder::class);
        $this->call(ArticlesTableSeeder::class);
    }
}

Finally, let’s go ahead and run our database seeders to get some data into our database:

$ php artisan db:seed

Laravel Lighthouse and GraphQL Server

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:

$ composer require nuwave/lighthouse:"3.1.*"

Next, let’s publish Lighthouse’s configuration file:

$ php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider" --tag=config

Note: You can also choose to publish Lighthouse’s default schema file by simply removing the <em>--tag=config</em> 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:

'schema' => [
    'register' => base_path('graphql/schema.graphql'),
],

So let’s go ahead and create our schema file and set up our user object type and query:

$ mkdir graphql
$ touch ./graphql/schema.graphql

/graphql/schema.graphql
type User {
  id: ID!
  name: String!
  email: String!
}

type Query {
  user(id: ID! @eq): User @find
  users: [User!]! @all
}

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 id, name and emailas fields that can be queried off our User models. Alternatively, this means that the password, created_at and 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 @alldirective 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:

$users = \App\User::all();

Note: *Lighthouse knows to look for a model in the <em>\App\User</em> namespace because of the *<em>namespaces</em>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:

$user = \App\User::where('id', $args['id'])->first();

Querying Our GraphQL API

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:

$ php artisan serve
Laravel development server started: <http://127.0.0.1:8000>

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:

{
  users {
    id
    email
    name
  }
}

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:

{
  "data": {
    "users": [
      {
        "id": "1",
        "email": "[email protected]",
        "name": "Carolyn Powlowski"
      },
      {
        "id": "2",
        "email": "[email protected]",
        "name": "Elouise Raynor"
      },
      {
        "id": "3",
        "email": "[email protected]",
        "name": "Mrs. Dejah Wiza"
      },
      ...
    ]
  }
}

Note: Because we used Faker to seed our database, the data in the <em>email</em> and <em>name</em> fields will be different.

Now let’s try querying for a single user:

{
  user(id: 1) {
    email
    name
  }
}

And we’ll get the following output for a single user:

{
  "data": {
    "user": {
      "email": "[email protected]",
      "name": "Carolyn Powlowski"
    }
  }
}

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 @paginatedirective readily available to us, so let’s update our schema’s query object like so:

type Query {
  user(id: ID! @eq): User @find
  users: [User!]! @paginate
}

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 users field.

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 PaginatorInfo type:

type UserPaginator {
  paginatorInfo: PaginatorInfo!
  data: [User!]!
}

type PaginatorInfo {
  count: Int!
  currentPage: Int!
  firstItem: Int
  hasMorePages: Boolean!
  lastItem: Int
  lastPage: Int!
  perPage: Int!
  total: Int!
}

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:

{
  users(count:2) {
    paginatorInfo {
      total
      hasMorePages
    }
    data {
      id
      name
      email
    }
  }
}

Which will provide us with the following response:

{
  "data": {
    "users": {
      "paginatorInfo": {
        "total": 11,
        "hasMorePages": true
      },
      "data": [
        {
          "id": "1",
          "name": "Carolyn Powlowski",
          "email": "[email protected]"
        },
        {
          "id": "2",
          "name": "Elouise Raynor",
          "email": "[email protected]"
        },
      ]
    }
  }
}

Relationships

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 Article type:

type User {
  id: ID!
  name: String!
  email: String!
  articles: [Article!]! @hasMany
}

type Article {
  id: ID!
  title: String!
  content: String!
}

Here, we’re using another Lighthouse provided schema directive @hasMany, which tells Lighthouse our User model has a \Illuminate\Database\Eloquent\Relations\HasManyrelationship with the Article model.

Now let’s query our newly defined relationship:

{
  user(id:1) {
    articles {
      id
      title
    }
  }
}

This will provide us with the following response:

{
  "data": {
    "user": {
      "articles": [
        {
          "id": "1",
          "title": "Aut velit et temporibus ut et tempora sint."
        },
        {
          "id": "2",
          "title": "Voluptatem sed labore ea voluptas."
        },
        {
          "id": "3",
          "title": "Beatae sit et maxime consequatur et natus totam."
        },
        {
          "id": "4",
          "title": "Corrupti beatae cumque accusamus."
        },
        {
          "id": "5",
          "title": "Aperiam quidem sit esse rem sed cupiditate."
        }
      ]
    }
  }
}

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 Query:

type Article {
  id: ID!
  title: String!
  content: String!
  author: User! @belongsTo(relation: "user")
}

type Query {
  user(id: ID! @eq): User @find
  users: [User!]! @paginate
  article(id: ID! @eq): Article @find
  articles: [Article!]! @paginate
}

You’ll see that we added an optional relation argument to the @belongsTo directive. This tells Lighthouse to use the Articles model’s user relationship and assign it to the author field.

Now let’s query for a list of articles and grab their associated author:

{
  articles(count:2) {
    paginatorInfo {
      total
      hasMorePages
    }
    data {
      id
      title
      author {
        name
        email
      }
    }
  }
}

And we should get the following from our server:

{
  "data": {
    "articles": {
      "paginatorInfo": {
        "total": 55,
        "hasMorePages": true
      },
      "data": [
        {
          "id": "1",
          "title": "Aut velit et temporibus ut et tempora sint.",
          "author": {
            "name": "Carolyn Powlowski",
            "email": "[email protected]"
          }
        },
        {
          "id": "2",
          "title": "Voluptatem sed labore ea voluptas.",
          "author": {
            "name": "Carolyn Powlowski",
            "email": "[email protected]"
          }
        }
      ]
    }
  }
}

GraphQL Mutation

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:

type Mutation {
  createUser(
    name: String!
    email: String! @rules(apply: ["email", "unique:users"])
    password: String! @bcrypt @rules(apply: ["min:6"])
  ): User @create
}

Now let’s break this schema definition down. We’ve created a mutation called createUser which takes three arguments (name, email, and password). We’ve applied the @rules directive to both our email and 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:

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Create a new user.
     *
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $data = $this->validate($request, [
            'email' => ['email', 'unique:users'],
            'password' => ['min:6']
        ]);

        $user = \App\User::create($data);

        return response()->json(['user' => $user]);
    }
}

Now that we have our createUser mutation field set up, let’s go ahead and run it in GraphQL Playground with the following:

mutation {
  createUser(
    name:"John Doe"
    email:"[email protected]"
    password: "secret"
  ) {
    id
    name
    email
  }
}

We should get the following output:

{
  "data": {
    "createUser": {
      "id": "12",
      "name": "John Doe",
      "email": "[email protected]"
    }
  }
}

GraphQL Authentication and Authorization

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 resolver argument.

With the @field directive defined below, we’re telling Lighthouse when the login mutation is run, use the createToken method on our App\GraphQL\Mutations\AuthMutator class:

type Mutation {
  # ...

  login(
    email: String! 
    password: String!
  ): String @field(resolver: "[email protected]")
}

Note: You do not need to include the entire namespace here. In the <em>lighthouse.php</em> config file you’ll see we have the namespace defined for our mutations set as <em>App\\GraphQL\\Mutations</em> already—however, you could use the full namespace if you prefer.

Let’s use Lighthouse’s generator to create the new mutator class:

$ php artisan lighthouse:mutation AuthMutator

Next, let’s update our resolver function like so:

namespace App\GraphQL\Mutations;

use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class AuthMutator
{
    /**
     * Return a value for the field.
     *
     * @param  null  $rootValue Usually contains the result returned from the parent field. In this case, it is always `null`.
     * @param  mixed[]  $args The arguments that were passed into the field.
     * @param  \Nuwave\Lighthouse\Support\Contracts\GraphQLContext  $context Arbitrary data that is shared between all fields of a single query.
     * @param  \GraphQL\Type\Definition\ResolveInfo  $resolveInfo Information about the query itself, such as the execution state, the field name, path to the field from the root, and more.
     * @return mixed
     */
    public function resolve($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
    {
        $credentials = Arr::only($args, ['email', 'password']);

        if (Auth::once($credentials)) {
            $token = Str::random(60);

            $user = auth()->user();
            $user->api_token = $token;
            $user->save();

            return $token;
        }

        return null;
    }
}

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:

mutation {
  login(email:"[email protected]", password:"secret")
}

We should get a token sent back to us like so:

{
  "data": {
    "login": "VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE"
  }
}

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.

type Query {
  # ...
  me: User @auth(guard: "api")
}

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:

{
  "Authorization": "Bearer VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE"
}

Note: Replace the bearer token with the token you received when running the login query.

Now let’s run the me query:

{
  me {
    email
    articles {
      id
      title
    }
  }
}

We should get output that looks like this:

{
  "data": {
    "me": {
      "email": "[email protected]",
      "articles": [
        {
          "id": "1",
          "title": "Rerum perspiciatis et quos occaecati exercitationem."
        },
        {
          "id": "2",
          "title": "Placeat quia cumque laudantium optio voluptatem sed qui."
        },
        {
          "id": "3",
          "title": "Optio voluptatem et itaque sit animi."
        },
        {
          "id": "4",
          "title": "Excepturi in ad qui dolor ad perspiciatis adipisci."
        },
        {
          "id": "5",
          "title": "Qui nemo blanditiis sed fugit consequatur."
        }
      ]
    }
  }
}

Middleware

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.

type Mutation {
  # ...

  createArticle(title: String!, content: String!): Article 
    @field(resolver: "[email protected]")
    @middleware(checks: ["auth:api"])
}

First, let’s generate a mutation class:

$ php artisan lighthouse:mutation ArticleMutator

Next, let’s update the mutator with the following logic:

namespace App\GraphQL\Mutations;

use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class ArticleMutator
{
    /**
     * Return a value for the field.
     *
     * @param  null  $rootValue
     * @param  mixed[]  $args
     * @param  \Nuwave\Lighthouse\Support\Contracts\GraphQLContext  $context 
     * @return mixed
     */
    public function create($rootValue, array $args, GraphQLContext $context)
    {
        $article = new \App\Article($args);
        $context->user()->articles()->save($article);

        return $article;
    }
}

Note: We renamed the default <em>resolve</em> function to <em>create</em>. 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 Authorizationheader from our previous query in the “HTTP Headers” tab:

mutation {
  createArticle(
    title:"Building a GraphQL Server with Laravel"
    content:"In case you're not currently familiar with it, GraphQL is a query language used to interact with your API..."
  ) {
    id
    author {
      id
      email
    }
  }
}

We should get the following output:

{
  "data": {
    "createArticle": {
      "id": "56",
      "author": {
        "id": "1",
        "email": "[email protected]"
      }
    }
  }
}

Wrapping Up

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!

How to Consume a GraphQL API with Angular

How to Consume a GraphQL API with Angular

In this article, we will show you how to use Angular to Consume a GraphQL API.

To download the source code, visit the Consuming a GraphQL API with Angular Source Code.

For the complete navigation of this tutorial visit GraphQL ASP.NET Core Tutorial.

Preparing the Angular Project

After we have finished with the ASP.NET Core client app, let’s create an Angular app as well.

We are going to start by creating a new Angular project without navigation module and with CSS as default styles. As soon as creation is over, we are going to install a set of libraries required for the Apollo Client to work with Angular:

npm install apollo-angular apollo-angular-link-http apollo-client apollo-cache-inmemory graphql-tag graphql -- save

The next step is to modify app.module.ts file:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ApolloModule } from 'apollo-angular';
import { HttpLinkModule } from 'apollo-angular-link-http';
import { HttpClientModule } from '@angular/common/http';
 
import { AppComponent } from './app.component';
 
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ApolloModule,
    HttpLinkModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

We import the ApolloModule and HttpLinkModule files, required for the Appolo integration with Angular. But, we can see that HttpClientModule is included as well. That’s because in order to work properly, HttpLinkModule internally uses HttpClientModule.

Let’s move on.

In the same way that we created model files for the ASP.NET Core client application, we are going to create them here.

So, let’s create a new folder „types“ and inside several type files:

export type OwnerInputType = {
    name: string;
    address: string;
}


export type AccountType = {
    'id': string;
    'description': string;
    'ownerId' : string;
    'type': string;
}


import { AccountType } from './accountType';
 
export type OwnerType = {
    'id': string;
    'name': string;
    'address': string;
    'accounts': AccountType[];
}

Now, we can create a graphql.service.ts file and modify it as well:

import { Injectable } from '@angular/core';
import { Apollo } from 'apollo-angular';
import { HttpLink } from 'apollo-angular-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import gql from 'graphql-tag';
import { OwnerType } from './types/ownerType';
import { OwnerInputType } from './types/ownerInputType';
 
@Injectable({
  providedIn: 'root'
})
export class GraphqlService {
  public owners: OwnerType[];
  public owner: OwnerType;
  public createdOwner: OwnerType;
  public updatedOwner: OwnerType;
 
  constructor(private apollo: Apollo, httpLink: HttpLink) {
    apollo.create({
      link: httpLink.create({ uri: 'https://localhost:5001/graphql' }),
      cache: new InMemoryCache()
    })
  }
}

We have an instance of the Apollo service with all the required configuration (link and cache). Both properties are required and must be populated.

After these configuration actions, we are ready to create some queries.

Creating Queries and Mutations

Let’s modify the graphql.service.ts file, by adding our first query:

public getOwners = () => {
    this.apollo.query({
      query: gql`query getOwners{
      owners{
        id,
        name,
        address,
        accounts{
          id,
          description,
          type
        }
      }
    }`
    }).subscribe(result => {
      this.owners = result.data as OwnerType[];
	console.log(this.owners);
    })
  }

We are using the Apollo service with its query function to write the entire GraphQL query. We’re using the imported gql tag as well, in order to be able to write GraphQL code as a multi-line string.

Now, let’s modify the app.component.ts file in order to test this query:

import { Component, OnInit } from '@angular/core';
import { GraphqlService } from './graphql.service';
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent  implements OnInit{
 
  constructor(private service: GraphqlService) {
  }
 
  ngOnInit(): void {
    this.service.getOwners();
  }
  title = 'angulargraphqlclient';
}

As soon as we start the Angular application, we can inspect the result:

Excellent.

Here are all the other queries and mutations from the graphql.service.ts file:

Get by Id Query
public getOwner = (id) => {
    this.apollo.query({
      query: gql`query getOwner($ownerID: ID!){
      owner(ownerId: $ownerID){
        id,
        name,
        address,
        accounts{
          id,
          description,
          type
        }
      }
    }`,
      variables: { ownerID: id }
    }).subscribe(result => {
      this.owner = result.data as OwnerType;
    })
  }


Create mutation example
public createOwner = (ownerToCreate: OwnerInputType) => {
    this.apollo.mutate({
      mutation: gql`mutation($owner: ownerInput!){
        createOwner(owner: $owner){
          id,
          name,
          address
        }
      }`,
      variables: {owner: ownerToCreate}
    }).subscribe(result => {
      this.createdOwner = result.data as OwnerType;
    })
  }


Update mutation example
public updateOwner = (ownerToUpdate: OwnerInputType, id: string) => {
    this.apollo.mutate({
      mutation: gql`mutation($owner: ownerInput!, $ownerId: ID!){
        updateOwner(owner: $owner, ownerId: $ownerId){
          id,
          name,
          address
        }
      }`,
      variables: {owner: ownerToUpdate, ownerId: id}
    }).subscribe(result => {
      this.updatedOwner = result.data as OwnerType;
    })
  }


Delete mutation example
public deleteOwner = (id: string) => {
    this.apollo.mutate({
      mutation: gql`mutation($ownerId: ID!){
        deleteOwner(ownerId: $ownerId)
       }`,
      variables: { ownerId: id}
    }).subscribe(res => {
      console.log(res.data);
    })
  }

You can test them by modifying the app.component.ts file, or if you want to create a new component to consume all these results.

Conclusion

We have learned a lot of great stuff about GraphQL and its integration with ASP.NET Core. Of course, with these last two articles, we went even further, by creating two client applications to consume our GraphQL app.

We hope you have enjoyed this tutorial and if you have any suggestions or question, don’t hesitate to leave a comment in the comment section. If you liked this post, share it with all of your programming buddies!

Further reading

☞ A Beginner’s Guide to GraphQL

Building a Secure API with GraphQL & Spring Boot

Building A GraphQL API With Nodejs And MongoDB

☞ GraphQL with React: The Complete Developers Guide

☞ How to create a simple CRUD App using GraphQL and Node.js

☞ Node, Express, PostgreSQL, Vue 2 and GraphQL CRUD Web App

☞ Developing and Securing GraphQL APIs with Laravel


Originally published on code-maze.com