In this article I will talk about one of my favorite feature when using Laravel framework. Yes, It's a response macro.
I will share you what it is and how we can use this feature to make our response more simpler and reusable.
Let's start it out!
What is response macro?
Response macro is a custom response that you can re-use in your routes or controllers.
When building a REST API, commonly you will use response()
helper to send data back to the user.
You also use some variants of response()
helper when you want to tell that the requested data is not found.
For example you will use these similar syntax to handle your REST API.
// Syntax when sending response with HTTP no content
return response()->json(null, 204);
// Syntax when sending response with HTTP not found
return response()->json(['message' => 'post not found'], 404);
// Syntax when sending response with HTTP created
return response()->json(['message' => 'register success'], 201);
Now, imagine. What if we can transform those response into simpler form but has same functionality?.
// Syntax when sending response with HTTP no content
return response()->noContent();
// Syntax when sending response with HTTP not found
return response()->notFound('post not found');
// Syntax when sending response with HTTP created
return response()->created('register success');
It's cool right? even those syntax tells us explicitly what actual action of those response send to the user.
How to add response macro?
Basically, we just extend the basic features of Laravel Response
object by registering our custom response inside App\Providers\AppServiceProvider
.
Open file app/Providers/AppServiceProvider.php
and use Illuminate\Support\Facades\Response
(Response facade). To register the custom response use Response::macro()
inside the boot
method.
Response::macro()
has two parameters. The custom response name and the implementation. Let's add one of the previous custom responses above.
<?php
namespace App\Providers;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Response::macro('notFound', function ($message) {
return Response::make(compact('message'), HTTP_NOT_FOUND);
});
}
}
How to use response macro?
If you have added the response macro, you can use it inside routes or controllers. For example you have a PostController.php
with method show
inside it.
<?php
public function show(int $id)
{
$post = Post::find($id);
if (is_null($post)) {
$message = sprintf('Post with id %d not found', $id);
return response()->notFound($message);
}
return new PostResource($post);
}
Bonus
Response macro is not about adding simple custom response only. You can use response macro as a transform layer (or service) to add micro functionality.
For example you can add response macro to convert markdown to HTML.
<?php
public function boot()
{
Response::macro('markdown', function ($raw) {
// fake markdown converter library
$md = new Markdown();
return Response::make(['data' => $md->toHTML($raw)], HTTP_OK);
});
}
Use it inside your controller.
<?php
public function render(int $id)
{
$post = Post::find($id);
if (is_null($post)) {
$message = sprintf('Post with id %d not found', $id);
return response()->notFound($message);
}
return response()->markdown($post->body);
}
NOTE:
When you use response macro as a transform layer, always remember to never put business logic inside it such a validation, database operations, etc.
Top comments (0)