How to share data across multiple api endpoints in Laravel
If you are developing an API built on Laravel that is intended for use in production, you might end up in a situation whereby there’s some data that ends up required across multiple endpoints. This tutorial will handle how to navigate this situation with some tools right from Laravel’s arsenal.
The code from this tutorial can be found on github on this link. Feel free to clone it to follow along.
Project setup
With the project cloned, setup the .env file with the environment variables and run composer update
to install the packages needed by Laravel to work.
Once the application is setup, setup the database with the tables and the dummy data needed for the endpoints using the following commands:
php artisan migrate
php artisan db:seed
Api endpoints
The application contains two endpoints which return the activities and notifications of a user, in this case the user with id 1.
/{id}/notifications
/{id}/activities
The aim of the tutorial is to return the notification count bundled with the data on both endpoints.
Defining the middleware
To alter the response from the two endpoints, we will use Laravel’s middleware.
Middleware, as defined by the docs, are a convenient mechanism for inspecting and filtering HTTP requests going into an application. While middleware are commonly known to be used to influence an application’s behavior before the request arrives at the controller level, they can be similarly deployed to perform tasks after the request has been processed and a response is being returned.
Create a new middleware to handle the problem of sending the notification count as part of the response.
php artisan make:middleware PassNotificationCount
Create a function in the middleware class to handle the query to draw the notification count.
protected function getNotificationCount()
{
return Notification::where(['notifiable_id' => 1])->whereNull('read_at')->count();
}
Code in the handle function will handle the logic with which the notification count will be added to the response, as so:
public function handle(Request $request, Closure $next)
{
$reponse = $next($request);
$notificationCount = $this->getNotificationCount(); $responseData = $response->getData();
$responseData->notificationCount = $notificationCount;
$response->setContent(json_decode($responseData)); return $response;
}
The statement $response = $next($request)
grabs the response object and stores it in the $response
variable. Invoking the closure $next
instructs the program to execute normally as it would have if it were not intercepted by the middleware.
In this case, it allows the code in the controller first, after which the code in the middleware will be executed.
The $response
variable has a few methods available to it, getData()
is one of these methods and returns the data embedded in the response as an object.
We can then add an attribute of notificationCount
to the object which we have and have the value of this attribute as the value obtained from the function obtained earlier.
The data in the $response
variable can be overridden using the setContent()
method which expects a single parameter of type string. We therefore have to encode the object.
With that, we can return the response to the normal flow of execution.
With the logic in the middleware out of the way, we still need to register the new middleware in the Kernel.php file.
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
...
...
...
'notificationcount' => \App\Http\Middleware\PassNotificationCount::class,
];
Once the middleware is registered, we can now add it to our routes so that whenever the endpoints are opened, the return value returns the notification count.
Route::middleware(['notificationcount'])->group(function () {
Route::get('/{id}/notifications', [NotificationsController::class, 'getNotifications'])->name('getNotifications');
Route::get('/{id}/activities', [ActivitiesController::class, 'getActivities'])->name('getActivities');
});
If you check on the two endpoints after the process, an extra attribute can be seen, containing the notification count.
Conclusion
With that, you can conveniently bind data across multiple endpoints without repeating your code.
Learn more about middleware from Laravel’s docs
And more about the methods used in the middleware here.