Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

dannydinges's avatar

Custom Exception Handler Based on Route Group

I'm trying to find a way to use a specific exception handler in Laravel 5 for two different route groups. I want to display a page based error page for one route group then for my api routes I want to display the error in json. Any direction on how to accomplish this?

0 likes
15 replies
dannydinges's avatar

Sorry I don't think I was clear in my first explanation. I'm trying to customize the Exception Handler to return a JSON response for a certain Route group but want it to return a view (custom error page) for another Route group. One is an API and one is a page based group. So not looking to return errors in the controller through the Response facade but instead I'm looking to catch all errors and return them as JSON for the API route group and a view for the page based route group. Hopefully that makes sense.

SachinAgarwal's avatar

@dannydinges in that case you can do something like this in your exceptions/handler.php file (Not tested, Not sure if it will work, but just a concept)

public function render($request, Exception $e)
{
    if($request->has('your api group prefix ')){
        // TODO convert the error to json format and return
    }
    
    return parent::render($request, $e);
}
2 likes
trevorg's avatar

I'm interested in doing the exact same thing. I would think this would also be necessary for distinguishing between web, AJAX and API calls, right?

trevorg's avatar

Here's what I did, and this works, but I'm not sure if it's the best way to accomplish this.

Basically in my .env I have:

APP_URI=app.domain.com
API_URI=api.domain.com

Then in app/Exceptions/Handler.php:

public function render($request, Exception $e)
{
       if($request->server->get('SERVER_NAME') == getenv('API_URI'))
    {
        if ($e instanceOf NotFoundHttpException)
                {
                    return \Response::json(['error' => ['message' => 'API endpoint not found.', 'status_code' => 404]], 404);
             }
    }
    return parent::render($request, $e);
}
1 like
cactus's avatar

we had similar request we did something like this which worked for us.

public function render($request, Exception $e)
{
    if($request->is('api/*')){
        return response()->json([
            'error_message' => $e->getMessage(),
            'status' => Response::HTTP_BAD_REQUEST
        ]);
    }

    return parent::render($request, $e);

}
4 likes
malhal's avatar

Thanks for the workaround, unfortunately it doesn't suit my case. I required a custom Handler class for the route group because I'm building a Laravel package, so I can't modify the existing Handler to add this if statement.

And btw cactus's example needs use Symfony\Component\HttpFoundation\Response;

malhal's avatar

Thanks but neither of those helped. I have figured out my own solution, not sure if there are any issues with it.

In my api_routes.php created by InfyOm Laravel Generator (but you could just put it in your API route group) I put this:

$this->app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\APIHandler::class
);

I believe this switches the exception handling from the original Handler class to a new APIHandler. Then I created this APIHandler class in the Exceptions folder, and in the render method have it render to JSON as in the above snippet by cactus (without the if statement). My only worry is about exceptions that might happen before it gets to the routing stage, if there are any?

4 likes
davestewart's avatar

Sweet - think I might be able to use that as well!

Did you just dump the app instance and look for exception references?

malhal's avatar

No I looked through the config and bootstrap folders and found where it is originally set in bootstrap/app.php

1 like
malhal's avatar

Sorry my solution doesn't work because it turns out Route::group gets executed even if the URL path does not match. This means it isn't possible to change the exception handler depending on the route group.

malhal's avatar

Think I've solved this now, switch the handler in the controller constructor like this:

class RestApiController extends Controller
{
    public function __construct()
    {
        \App::singleton(
            \Illuminate\Contracts\Debug\ExceptionHandler::class,
            RestApiHandler::class
        );
    }
2 likes
jwadhams's avatar

We used malhal's solution (switching the ExceptionHandler singleton) except that we created a new middleware group, created a middleware that runs App::singleton to change the exception handler, and ordered that middleware first in the group. (So that exceptions in other middlewares run with the right handler.)

1 like

Please or to participate in this conversation.