Building a delighted RESTful API with Laravel

09 Jan 2019 . Laravel . 6.4K views

Writing API with Laravel considering easy, however writing delightful API with Laravel is not that easy. To write a delighted API, you need to have a proper plan for your API.

I am planning to share my personal opinion on how to write an incremental API with Laravel. As a consequence, I am going to share you first, how to plan a Laravel API that everybody love.

First of all, we need to define two types of structural elements for planning a lucrative API via Laravel. Two structural elements are-

  • Rules for defining API End-points

  • Rules for writing Code

Today, in this tutorial, I am going to share how to define the rules for RESTful API end-points.

Rules for defining API End-points

In my personal experience, I realized that defining rules for writing API end-points is really crucial to write manageable API. So, that first step for API plan is to define the rules how to define a new API end-points. It will help to follow a systematic end-point for the development team.

If you decided to use RESTful style for your API, you need to strictly follow the RESTful syntax. Besides, it should completely depend on the HTTP Verbs. In addition, the developer should not be allowed to write any CUSTOM METHOD.

End-point syntax:

api/{versionNumber}/{resourceName}/{actionName}

Terminology:

There is some terminology I have used in the above syntax. Let me introduce you all syntaxes.

  • A resource is an object or representation of something, which has some associated data with it and there can be a set of methods to operate on it. E.g. Users, Posts, Shops, and Products are resources and delete, add, update are the operations to be performed on these resources.

  • Collections are a set of resources, e.g Shops is the collection of Shop resource.

  • URL (Uniform Resource Locator) is a path through which a resource can be located and some actions can be performed on it.

Let's see some example on that API end-point syntax.

End-point Example:

GET		api/v3/shops			// show list of shops
POST	api/v3/shops/create		// create a new shop
GET		api/v3/shops/11			// show a shop details of shop id = 11
PUT 	api/v3/shops/11			// update	
DELETE	api/v3/shops/11			// delete a shop of id = 11 

Sub End-point syntax:

Sometimes, you need to define subresources for a resource. In this case, you need to follow the following structure.

api/{versionNumber}/{resourceName}/*/{subResourceName}/*

Imagine that, you have a sub-resource called products that belong to a resource called shops. Let's see how the endpoint will be-

End-point Example:

GET		api/v3/shops/11/products			// show list of products of shop id = 11
POST	api/v3/shops/11/products			// create a new product of shop id = 11
GET		api/v3/shops/11/products/1			// show a product details of id = 1 from shop id = 11
DELETE	api/v3/shops/11/products/1			// delete a product of id = 1 where shop of id = 11 

For some reason, you need to define the sub of sub-resources too. In that case, you need to follow the same structure also.

api/{versionNumber}/{resourceName}/*/{subResourceName}/*/{subSubResourceName}

Resource Naming Convention

The next important to follow the same naming convention for defining a resource, so that the structure of the API end-point will be the same style from every developer.

Imagine that, a shop has a shop fan page. So, the resources and sub-resources for this naming convention should be-

GET api/v3/shops/{shopId}/fanpage

Instead of-

GET api/v3/shops/{shopId}/shopFanpage

How to define a Group of End-points

Sometimes you need to define a group of API endpoints those are working for the same resources. In this case, it is my opinion to use Route::prefix() instead of individual end-points to organize the code. For example, imagine you have a shops resource that has few restful actions. The route should be like this-

Route::prefix('shops')->group(function(){
	Route::get('/', '[email protected]')->name('shops');
	Route::get('{shopId}', '[email protected]')->name('shops.show');
	Route::post('/', '[email protected]')->name('shops.create');
	Route::put('/', '[email protected]')->name('shops.update');
	Route::delete('/', '[email protected]')->name('shops.delete');
});

It's also required to wrap resource and subresource in some cases. In that situation, you can use the prefix to wrap another prefix. For example, imagine you have a shop's resources and products as a sub-resources, where end-points will be like this-

Route::prefix('shops/{shopId}')->group(function(){
	Route::prefix('products')->group(function(){
		Route::get('/', '[email protected]')->name('products');
		Route::get('{productId}', '[email protected]')->name('products.show');
		Route::post('/', '[email protected]')->name('products.create');
		Route::put('/', '[email protected]')->name('products.update');
		Route::delete('/', '[email protected]')->name('products.delete');
	});
});

Field Expansion:

If you want to get the GET /products query, it will return entire objects and also paginated the results. This is common for most edges. In that case, you can also add limit and order the results.

Limit

You can limit down your result during fetching data.

api/v3/shops/*?fields=all&limit=3

The above link should return all the field where just return 3 results.

Order

You can order your result based on resource creation time.

api/v3/shops/*/orders?fields=all&order=chronological&limit=3

Here, it will fetch orders of a particular shop in chronological order by limiting down 3 results. The types of order should be-

  • chronological — orders results with the oldest created objects first.

  • reverse_chronological — orders results with the newest created objects first.

Hope you love my idea. In the next tutorial, I will show you how to set rules for writing the code. Thank you. :)