DEV Community

Cover image for Laravel response macro
M. Akbar Nugroho
M. Akbar Nugroho

Posted on • Edited on

Laravel response macro

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);
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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);
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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);
    });
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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)