Create Simple API using Laravel Lumen and Improve Its Error Handling

Hanief
Remote Worker Indonesia
9 min readSep 20, 2021

Good day friends! 😊

How is your day? Good? Still in love with code? 😊

Today we will explore about how to create a simple registration API using Laravel Lumen and of course improve its error handling too.

One of my experiences in creating and consuming an API is that API makers often don’t pay attention to its error handling.

This article can be one of guide for you to create an API using Laravel Lumen and how to improve its error handling. This article will explore too about how to use some of Laravel feature named: migration, seeding and factory.

Prologue

Before we start the code, let’s define simple case for our API

Problem : We will create a registration API that handle a CRUD process and return a response that show is there something wrong with request or API process.

Requirement:

  1. apache and PHP or similiar server service (nginx, xampp, wampp, laragon, etc).
  2. MySQL database or other RDMS
  3. composer installed on your CLI

I have create a github repository for this case

Implementation

Project

Let’s start our code with creating new Laravel Lumen project (we will named it registration_api).

Open your CLI and then run this command:

composer create-project --prefer-dist laravel/lumen registration_api

Wait a moment until the process is complete. After the process completed, let’s check if Laravel Lumen has been installed correctly with command:

cd registration_api
php -S localhost:8000 -t public

Ok the service has running. Let’s check in our browser

http://localhost:8000

Alright it’s worked nicely.

Database & Table

Let’s start our code with thinking about its database structure. This is an API for registration, So, this is some fields that we need for it (in my mind):

  1. id, of course for primary field
  2. name, varchar and mandatory field
  3. id_card_number, 16 maximum-long-number and mandatory field
  4. address, text field and not mandatory
  5. phone, 15 maximum-long-number field and not mandatory

Ups, we forgot to set up our laravel to connect the database. Before we set it up, don’t forget to create a database first. Open your CLI, then run this command (MySQL / mariaDB database):

mysql -u root -p
Enter Password:
mysql > CREATE DATABASE `registration_api`;
Query OK, 1 row affected (0.02 sec)

Some explanation:

  • I use MySQL RDMS, so if you use another RDMS please search how to do it in your RDMS.
  • You must know what is your database user and password, put your database user after -u and your password after -p
  • If you run right query, message Query OK will appear.

After we create the database, let’s set up the database environment in our project. Open .env file and adjust the setting in it.

...
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=registration_api
DB_USERNAME=root
DB_PASSWORD=
...

Alright, we ready to use it.

You can manually create a table based on what we designed before, but in this article we will use on of Laravel (and most of latest framework) feature: migration.

It’s so easy to create a migration, run this command in CLI on your project folder: (we will create table registrants)

php artisan make:migration create_registrants_table
Created Migration: 2021_09_20_020453_create_registrants_table

It will be generate file 2021_09_20_020453_create_registrants_table on folder /database/migrations. Open the file and change the code based on table design like this:

Run this command in your CLI to start the migration process:

php artisan migrate
Migration table created successfully.
Migrating: 2021_09_20_020453_create_registrants_table
Migrated: 2021_09_20_020453_create_registrants_table (44.94ms)

Ok, the database and table is ready. Let’s move to the API.

API

For the API, we will create a CRUD process for registrant which the table we have created. This is the API design in my mind:

  1. Show all registrant data
  2. Get one of registrant data using its ID
  3. Add one new registrant
  4. Change / Update registrant data
  5. Delete registrant data

Based on this design, we create a new file RegistrantController.php in folder app/Http/Controllers with this code as content:

Ups, we forgot to activate Eloquent and create a Model for registrant. Let’s do it before we continue.

Open file bootstrap/app.php and then remove comment block for Eloquent on line 28

...
$app->withEloquent();
...

Create a new file with name Registrant.php in folder app/Models with this code for content:

To access the controller we made, we must create a router for it. Open file web.php in folder routes and then create some router for our API like this:

In code above, we create 5 router for our API with prefix api/ with explanation like this:

  1. api/registrants is an API with GET method to show all of registrant data. This API access file RegistrantController.php function index().
  2. api/registrant is an API with POST method to insert registrant data. This API access fileRegistrantController.php function create().
  3. api/registrant/{id} is an API with GET method to get one of registrant based on id requested by user. This API access file RegistrantController.php function show().
  4. api/registrant/{id} is an API with PUT method to do an update one of registrant data base on id requested by user. This API access file RegistrantController.php function update().
  5. api/registrant/{id} is an API with DELETE method to delete one of registrant data. his API access file RegistrantController.php function destroy().

Ok, the API is ready. Hmm… but the data is still empty, what we must do? Manually input it one by one?. Don’t worry, Laravel provide a solution for this case named: seeding.

Seeding

Seeding is one of Laravel feature to generate dummy data for our database with purpose to show how an API will be look before we input the real data.

This is how we create a seeding.

First, we must create a seeder file using this command:

php artisan make:seeder RegistrantsTableSeeder

It will be generate a file named RegistrantsTableSeeder.php in folder database/seeders. Before we continue with this file, we will use another feature of Laravel called factory. Like its name, it’s like a factory that will produce data we need for our seeder.

To use factory feature, create a file with name RegistrantFactory.php in folder database/factories with this code as its content:

Okay, the factory is ready, let’s move our seeder file database/seeders/RegistrantsTableSeeder.php.

In this seeder, we create 10 dummy data for our API. To execute this seeder we can use this command on our CLI:

php artisan db:seed --class=RegistrantsTableSeeder
Database seeding completed successfully.

Or we can first register it on file DatabaseSeeder.php in folder database/seeders first like this:

And then executed this command on our CLI:

php artisan db:seed
Seeding: Database\Seeders\RegistrantsTableSeeder
Seeded: Database\Seeders\RegistrantsTableSeeder (130.71ms)
Database seeding completed successfully.

Okay, seeding is done. Let’s move to how to access our API.

Access the API

To access the API, we will use POSTMAN as a application that consume our API because it’s easy to use and can show how our API response looks like.

I create a Postman Collection for this case, you can download it and import it. This where the file is.

Let’s start from our first API:

  • show all registrant data.

This is our request on Postman:

We use GET as a request method and access url: http://localhost:8000/api/registrants . Click on [Send] button to run the request, the response will appear on the below of request area.

  • insert new registrant data.

We use POST as a request method and access url: http://localhost:8000/api/registrant . Don’t forget to open [Body] tab and add the data for name, id_card_number, address, phone. Click on [Send] button to run the request, the result will be showed.

  • get one of registrant based on id requested by user

We use GET as a request method and access url: http://localhost:8000/api/registrant/5 . Like what we requested in the url, we want the API to show data of registrant with id 5. Click on [Send] button to run the request, the response will appear on the below of request area.

  • update one of registrant data based on id inputted by user

We use PUT as a request method and access url: http://localhost:8000/api/registrant/5 . Like what we requested in the url, we want the API to update data of registrant with id 5. We put the modified data on tab [Body] then pick [raw] radio button. Don’t forget to change the content type to JSON.

This is JSON of the modified data we put:

{
"name": "Prof. Glen Grimes II",
"id_card_number": "5160201003975662",
"address": "518 Roderick Mission Apt. 997\nPowlowskimouth, AL 89818-6209",
"phone": "1-317-243-1855"
}
  • delete one of registrant data based on id inputted by user

We use DELETE as a request method and access url: http://localhost:8000/api/registrant/11 . Like what we requested in the url, we want the API to delete data of registrant with id 11.

Improve Error Handling of our API and Why?

No one like an error

It’s true, no one like an error on his life. But it can’t be denied because we are human, so we sometimes made an error.

Same with our code, sometimes error occurred because of wrong code we made, something wrong with the machine, the database connection can’t be established, insufficient required parameter for our API, etc.

To handle an error that may occurred with our API, we must think what issue might happens with our code. This is some of the issue I can think:

  1. The API response presented didn’t have same structured and not informative enough.
  2. Can’t connect to the database (maybe because we aren’t activate it yet or wrong configuration).
  3. User forgot / not filled required parameters.

Let’s start with improving our API response, We will use this structure for our API response:

{
"timestamp": "",
"status": "",
"message": "",
"results": ""
}

Explanation:

  • timestamp : show what time API accessed (format: yyyy-mm-dd hh:mm)
  • status : status of API, using HTTP basic response (200 : for success, 500: for error server, etc)
  • message : show message of API (mostly for error message), empty if success.
  • results : show array of data when accessed the show all data and get one data API

This is our controller code RegistrantController.php when we improve our API response.

Explanation:

  • Every API accessed, we will always create a basic response using function basic_response() and then put other response on each API. This happened because we set it in function __construct().
  • We create an error handling to check if database connected correctly or not using code:
try {
// the code
} catch (\Throwable $th) {
// set error code and message
}
  • For API that need validation for parameter that POST-ed by user like insert new data and update, we using this code:
$validator = $this->getValidationFactory()->make($request->post(), $this->validation_rules);if ($validator->fails()) { 
// set error code and message
} else {
// the code
}

Don’t forget to set the variable $validation_rules

  • For API that need validation for parameter that embedded in the url like get one data or delete, we using this code:
$validator = $this->getValidationFactory()->make(['id' => $id], ['id' => 'required|numeric']);if ($validator->fails()) {
// set error code and message
} else {
// the code
}
  • We use status 200 if API success, 422 if there’s a required parameter not filled by user, 500 if there’s something wrong with our server.

This is our API response looks like after we improve its error handling.

Looks more informative, right? 😁

Conclusion

We have create a simple registration API using Laravel Lumen and using Postman apps to test it out. Not to forget, we using some of Laravel feature too named : migration, seeding and factory. It’s done nicely! 😁

Thank you for your time to read. Let’s join us again next time as we explore another interesting case! 😉

--

--