Building a good REST API is crucial to security, reliability, and maintainability. How can you ensure the quality of your REST API? Use a good development pattern!
Introduction
In her article "What is a REST API?", Catherine Dee defines REST APIs in the following manner: "An API is a software intermediary that lets software programs connect and communicate with each other... REST is a collection of rules that developers follow when creating APIs; a set of principles governing how different programs communicate. So a REST API is simply an API that applies these principles."
In this article, we'll talk about good naming and saving patterns and how to use them so that your development process is clear and efficient.
Routes
A route is a path where we can access some resource. The best file to create it is routes/api.php. Here's a simple CRUD example of managing a resource called "company":
<?php
//Company routes
Route::group(['prefix' => 'company'], function () {
Route::post('/', 'CompanyController@create');
Route::get('/', 'CompanyController@read');
Route::put('/{companyId}', 'CompanyController@update')->where('companyId', '[0-9]+');
Route::delete('/{companyId}', 'CompanyController@delete')->where('companyId', '[0-9]+');
});
It's a good practice to create a group with the same name of the resource. Doing so makes it easy to read the code and find everything related to the resource whenever you need to make a change. In the example above, certain REST rules are being used: POST to create, GET to read, PUT to update, and DELETE to remove a resource. We are also doing a simple validation on the 'companyId' parameter, which should be numeric. There are a lot of validations that we can use, and I talk more about this in The Best Way to Use Request Validation in Laravel REST API,
Controllers
In Laravel, controller files should be in app/Http/Controllers/ folder. If more than one controller is needed to manage a resource, a folder with its name should be created. The code below shows a controller for company.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\Company\CreateCompanyRequest;
use Illuminate\Http\JsonResponse;
use App\Services\CompanyService;
class CompanyController extends Controller
{
/**
* Constructor to instantiate Request
* @param CompanyService $companyService
*/
public function __construct(CompanyService $companyService)
{
$this->companyService = $companyService;
}
/**
* Create a Company
* @param CreateCompanyRequest $createCompanyRequest
* @return JsonResponse
*/
public function create(CreateCompanyRequest $createCompanyRequest) : JsonResponse
{
$params = $createCompanyRequest->all();
$companyCreated = $this->companyService->create($params);
return response()->json($companyCreated);
}
}
?>
A controller method should be really simple. Its responsibility is to manage the flux and set a proper request validation. On the create method, we receive a CreateCompanyRequest parameter that handles all validations that are needed. Its job is to grab them and pass them to companyService, which knows what to do next.
Services
There is no Service folder by default in Laravel, but I recommend creating one in your app folder. If more than one service is needed to manage a resource, a folder with each name should be created. The code below shows a service for company:
<?php
namespace App\Services;
use App\Models\Company;
class CompanyService
{
const DUPLICATED = 'Empresa duplicada';
/**
* Create a Company
* @param array $params
* @return array
*/
public function create(array $params) : array
{
//Check duplicates
$exists = $this->getCompanyByCnpj($params['cnpj']);
if (!empty($exists)) {
return ['msg' => self::DUPLICATED];
}
$company = new Company();
$company->name = $params['name'];
$company->cnpj = $params['cnpj'];
$company->address = $params['address'];
return $this->save($company);
}
}
?>
In the service file, there is a create method that does what is needed to save Company objects on the database. First, we need to check if we already have a company with the same identifier on the database. It would not be good to add all the verification inside this method, so we have created a dedicated method to do this called getCompanyByCnpj. After that, a Company object is created and passed to another method called "save". This method was created to be reutilized by an update method as well.
Let's suppose we need to communicate with another app or microservice to get data or to do some verifications. In this case, it's advisable to create another service file to perform this task; you could name it CompanyAPIService, for example.
Conclusion
Building a REST API is a good way to deliver data to any service. There are many ways to create it, but using a standard pattern helps you save time both during development and after whenever a new feature is needed.
Want to learn more about REST APIs in Laravel? Check out my article on the best way to use request validation!
Author
Luiz Henrique Santos
Luiz Henrique Santos is a Full Stack PHP Developer at Avenue Code with 7+ years of experience in IT. He always tries to understand functionalities to propose the best solution while working to deadlines. He applies SOLID standards, develops code that is easy to read and change, and writes unit tests for everything he does!