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

rudolfbruder's avatar

Laravel custom exceptions handling

Hi,

I am looking for maybe a better way of doing this or opinions whether this is normal way of handling exception in a project. Imagine that I have a service class which has this method in it which updates an eloquent model. If it fails i have custom exception which has logging to custom channel, slack notifcation and other stuff in the report method. Here is the method of the service:

    public function updateTransformatorData(EsoDataLoader $esoDataLoader, array $transformatorData): bool
    {
        try {
            $result = $esoDataLoader->update([
                'transformator_data' => json_encode($transformatorData)
            ]);
        } catch (\Throwable $th) {
            throw new EsoDataLoaderException(['esoDataLoader' => json_encode($esoDataLoader), 'transformatorData' => json_encode($transformatorData)], 'Problem with saving trasnformator data', EsoDataLoaderException::CODE_LOADER_TRANSFORMATOR_DATA_UPDATE_PROBLEM, $th);
        }

        return $result;
    }

And now here is it's usage in other class somewhere in the project:

        try {
            eso()->service()->updateTransformatorData($this->esoDataLoader, $this->transformatorClassesToBeRunCollection->pluck('title')->toArray());
        } catch(EsoDataLoaderException $ex) {
            report($ex);
        } catch (\Throwable $th) {
            throw $th;
        }

What I find strange is that anywhere in the project where some service throws my custom exception, I have to catch it and specifically run the report($ex) method in order to handle the logging and slack notification. I find that pretty redundant but I did not find any other way to do it.

I mean yes I can use the report helper in the service itself but that would mean that the application would continue and not stop on the exception which is not correct either.

Is there a better approach for this problem please?

0 likes
13 replies
martinbean's avatar

@rudolfbruder Laravel has an exception handler for, well, handling exceptions.

You should be throwing exceptions from your code, and then using the exception handler to do any reporting, converting them to HTTP responses, etc. Otherwise your code is just going to end up stuffed with try/catch blocks and duplicated handling logic spread across your codebase.

From https://laravel.com/docs/9.x/errors#reporting-exceptions:

For example, if you need to report different types of exceptions in different ways, you may use the reportable method to register a closure that should be executed when an exception of a given type needs to be reported.

rudolfbruder's avatar

@martinbean I unedstand that there is handler.php file but we are about to have a lot of exception. Should I have them in one file and their logic? I don't like that very much.

Also if everything is in handler what is the report() method for in the Exception? Based on https://laravel.com/docs/9.x/errors#renderable-exceptions I understand that it's the exact case when I dont want to use handler.php. I guess my problem is that the report() method on my custom exception is not called when it is catched by another try catch in parent method.

martinbean's avatar

I unedstand that there is handler.php file but we are about to have a lot of exception. Should I have them in one file and their logic? I don't like that very much.

@rudolfbruder Why? That’s literally the purpose of the exception handler? Where else are you going to handle your exceptions? In every single place in your application where an exception could be conceivably thrown? Then as I say, your application code is just going to end up full of try/catch blocks with the same exception handling logic repeated every where you catch the same types of exceptions.

Also if everything is in handler what is the report() method for in the Exception? Based on https://laravel.com/docs/9.x/errors#renderable-exceptions I understand that it's the exact case when I dont want to use handler.php. I guess my problem is that the report() method on my custom exception is not called when it is catched by another try catch in parent method.

I don’t think you’ve quite read and understood the documentation I’ve linked you to. You can add callbacks for specific exception types and then customise the reporting logic. This was based in response to your original post:

If it fails i have custom exception which has logging to custom channel, slack notifcation and other stuff in the report method. Here is the method of the service

So you’d move that reporting logic to a callback in your exception handler:

$this->reportable(function (YourCustomExceptionClass $e) {
    // Report using a different logging channel, send Slack notifications, etc.
});

This isn’t really necessary though if you just used a decent log aggregator like Bugsnag or Sentry.

rudolfbruder's avatar

@martinbean nice I think I understand it now, so basically what I have now in the report() method should be within the callback in handler class - which will be called whenever the exception is thrown anywhere in the app anytime.

What I don't understand what is the reason to have the report() method on a custom exception. I have read the docs again and I understand it's supposed to be kind of a rare case scenario when I need to report the exception but continue the app flow. I dont quiet understand this from docs:

'Laravel will deduce what type of exception the closure reports by examining the type-hint of the closure:'

Sinnbeck's avatar

@rudolfbruder in Martin's example he type hints YourCustomExceptionClass. That thing before the variable is a type hint

rudolfbruder's avatar

@Sinnbeck Ok I understand thank you. Guys what I am still trying to figure out is this. Imagine you have a controller which does something - calls service method. That method throws my CustomException.

I have it registered in handler.php like this:

        $this->reportable(function (OrderFromEsoException $e) {
            info('I am here and i can do what i want.' . $e->getMessage());
        });

This would be my service method:

public function serviceMethod()
    {
        try {
            User::create([]);
        } catch (\Throwable $th) {
            throw new CustomException([], 'test', 123); // this would be thrown by the service
        }
    }

And this controller method:

    public function index()
    {
        try {
            //some logic in controller which throws exception
            serviceMethod();
        } catch (\Throwable $th) {
        }
        return $homeService->resolveCurrentEshopView();
    }

My problem is that index() method and the exception that is thrown is not reported in this case because there is a catch() in the controller. Is that a bad approach please? Is it better to have no try catch in the controller and just rely on throwables and their reporting from within the service classes? What if I want the logic to continue even through the exception in the controller? Should I use try catch and user report() helper function in the catch block?

Thank you very much for your time.

martinbean's avatar

@rudolfbruder I don’t really know how many times I can say the same thing? Yes, your custom exception from your service class is not going to reported properly if you just catch it in your controller. I’ve said multiple times now that you use the exception handler to avoid putting shit loads of try/catch blocks in your application code.

Your controller should just be calling methods and handling results. Let the exception handler handle exceptions:

class SomeService
{
    public function someServiceMethod()
    {
        if ($somethingWentWrong) {
            throw new SomeServiceException('Error explaining what went wrong');
        }
    }
}
class SomeController extends Controller
{
    public function someAction(SomeService $someService)
    {
        $result = $someService->someServiceMethod();

        // Return response...
    }
}

You don’t handle exceptions in the controller. It’s not the responsibility of the controller. Handling exceptions is the responsibility of the exception handler.

1 like
rudolfbruder's avatar

@martinbean ok thanks Martin. I am familiar with you and your profile over here and I believe you have a lot of experience but you dont need to be grumpy.

Thanks all of your for your time and effort its clear for me now, much appreciated.

rudolfbruder's avatar

@martinbean yeah a bit but it''s all right. Ok I understand it. So I will stick to handler.php. If I undestand it correctly it is perfectly fine to use try catch blocks in service classes and their method and in the catch or some if statement logic where in case I am not happy I can throw custom exception which will then be handled by well the handler.php. Is that correct approach according to you?

martinbean's avatar
Level 80

@rudolfbruder You’d throw custom exceptions from your service classes, but you wouldn’t catch them in there (as per my example) otherwise they won’t reach the exception handler for handling.

2 likes

Please or to participate in this conversation.