minaremonshaker's avatar

Managing API Exception Handling with Custom Formats in bootstrap/app.php

Hello, I am developing an API and want to handle exceptions in a specific format. I have added this format to the bootstrap/app.php file, but I want to avoid putting too much code in that file. Is it possible to extend the NotFoundHttpException and customize its response so that it appears according to my desired format? If this is possible, how can I apply it within bootstrap/app.php? Additionally, I want to use the same schema for other global exceptions—how can I achieve that? I have included my bootstrap/app.php code here for reference: https://gist.github.com/mina20088/06992136c0d18b532cc34a9faa2c2362.

0 likes
14 replies
Glukinho's avatar

For example, you can extract the whole complex closure to some class with static method and use like this:

// app.php

$exceptions->render(ExceptionsResponseSchema::render(...));


// ExceptionsResponseSchema.php

public static function render(\Throwable $exception, Request $request)
{
    match(get_class($exception)) {
       NotFoundHttpException::class => return /* some logic */,
        /* etc */
    };
}

Is it possible to extend the NotFoundHttpException and customize its response

I'm not sure Laravel will use your new extended exceptions instead of builtin ones. You should try. If extended exceptions are applied, you can utilize render() method in them: https://laravel.com/docs/12.x/errors#renderable-exceptions

Glukinho's avatar

Extracting this logic to a separate class is exactly what I proposed.

Two considerations:

  1. don't you reinvent the wheel? I mean, do you really need such a complex JSON in API response?
    Also, why you duplicate HTTP response code and type in JSON? These values can be taken from HTTP status code and phrase itself. I mean, if a user gets HTTP response 404 Not Found why duplicate it in JSON like this:
{
    ...
    "type": "NOT_FOUND_EXCEPTION",
    "statusCode": 404,
    ...
}
  1. the code building the response is highly duplicated - it creates many almost identical arrays with only some exception-specific fields. You can simplify it by building an array with all common fields and transform specific fields afterwards.
minaremonshaker's avatar

Could you please provide me with a schema that I can use for all my responses—including errors, data, and other cases? Also, if possible, could you include a code example to help me better understand point number 2? Thank you in advance.

minaremonshaker's avatar

For point 1, you mean that when consuming the API from a SPA like Vue using Axios or the Fetch API, the response already includes the 404 status, so there’s no need to include it again, right?

Glukinho's avatar

Ok, I will when I'm at a computer, tomorrow.

What data do you think your API users need? Do they really need traces and file names and line numbers of your code? Or it is just for you while developing?

response already includes the 404 status, so there’s no need to include it again, right?

Yes, HTTP response already has status code which describes what is wrong quite well. 404 means "not found", no need to have it again inside response body unless you have special needs.

minaremonshaker's avatar

Thank you very much. This is my first time creating an API, so I’m not yet familiar with the conventions.

Glukinho's avatar

First of all, why you implement your own structure? What is wrong with Laravel builtin JSON errors?

minaremonshaker's avatar

what do you think if i made the method like this

minaremonshaker's avatar

i just want all of my response to be same , think this is one of the restful api convinsions , correct me if i am wrong

Glukinho's avatar

My suggestion is to stick to standard Laravel responses until you really know why you need a custom structure. Otherwise you can spend a lot of time reinventing the wheel while clients of your API don't need it at all.

Simple abort(404, 'I haven\'t found anything'); will give you nice response:

HTTP/1.1 404 Not Found

{
    "message": "I haven't found anything"
}

If you have APP_DEBUG=true in .env this JSON will be appended with stack trace which is useful for debugging. That's all, do you really need something more complex?

If you want to stick to your structure, I would go with something like this:

After that use it in app.php:

$exceptions->render(ExceptionSchema::render(...));

But again, Laravel already does the same inside.

martinbean's avatar
Level 80

i just want all of my response to be same , think this is one of the restful api convinsions , correct me if i am wrong

@minaremonshaker Your responses will be the same if you just let Laravel’s exception handler do what it says on the tin, and let it handle exceptions.

And as someone else has pointed out, there’s absolutely zero point including things like 'success' => false and 'statusCode' => ResponseAlias::HTTP_NOT_FOUND in your response body when that’s the entire point of the response status code. You don’t need statusCode in the body when it’s in the headers. You also don’t need a success key because if I get a 4xx or 5xx response, then it’s clear it wasn’t successful.

Auqcion's avatar

You could also add something like this to keep the conversation moving:


One more thing worth noting: if your main goal is simply consistent formatting, you don’t actually need to manually match every exception in your schema. Laravel already maps most exceptions to proper HTTP codes, so you can just read the status from $exception->getStatusCode() when available:

$status = method_exists($exception, 'getStatusCode')
    ? $exception->getStatusCode()
    : 500;

That way your schema stays clean, and you only override types/messages when you really need custom behavior. It also means your global handler works automatically for future exceptions without updating match() every time.

This keeps your bootstrap/app.php small while still giving you full control over the output format.

Please or to participate in this conversation.