HOW TO DEAL WITH EXCEPTIONS IN LARAVEL
Tags: laravel, php, backend
Published: 2024-06-09 17:06:03

Laravel is a free and open-source PHP web framework, created by Taylor Otwell and intended for the development of web applications, Laravel is based on Symfony ([wiki](https://en.wikipedia.org/wiki/Laravel)).

The Framework provides a lot of features to help developers improve the error handling avoinding your application returns an unexpected errors, in this post you can learn more about how to deal with exceptions in laravel. 

## &nbsp;

## Exceptions
You may be asking "how can i deal with errors better than a simple try catch block code?"

```php
public function index()
{
    try {
        //do anything...
    } catch(ExampleException $exception) {
        return response()->json([
            'error' => 'An error occurred.'
        ], 500);
    }
}
```

The above code is the most commun way that people deal with exceptions and it is not wrong, but it can be better, you can notice that the code is not the most secure way, if the `ExampleException` dispatches in elsewhere in the code you may add the try catch block in every place that the exception can be thrown, and sometimes you just don't know where it can be dispatched, but, what if there was a way to catch the exception regardless of where it is thrown?

## &nbsp;
## Laravel Error Handling

There is a way to deal with any and all exceptions that your code raises and add logs, also send error reports to the cloud/email, thus having greater freedom to deal with errors in your system, allowing you to be aware of any error your project triggers in any code flow. Starting with version 11 of Laravel, it is possible to access the `bootstrap/app.php` file and view some rules that Laravel must follow during the initialization period of your application, in our case we will focus on the `withExceptions` method, which allows us execute some code when an exception is thrown.

```php
->withExceptions(function (Exceptions $exceptions) {
    //
})
```

As you can see, the `withExceptions` method receives as a parameter a class called `Exceptions`, this class provides a series of methods that help you deal with exceptions thrown in your application. In this article, we will only look at the methods that you will probably use in your day-to-day life, but you can see all the methods in the [documentation](https://laravel.com/api/11.x/Illuminate/Foundation/Configuration/Exceptions.html)

Before we see the usefulness of some methods, we need to understand the process (in a simplified way) of how exception throwing works within Laravel: 


![A simple example of laravel exceptiuns flow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e9shqspolkzq13mr7upl.jpg)

In the example above we can see that, before an exception is returned to the request response, Laravel saves a LOG of the exception regardless of whether you have a registered handler or not, and this behavior can be changed according to the needs of your application. This allows you to prevent Laravel from saving logs automatically and you can choose exactly which log you want to save and in which log channel to save it, making your application more standardized and modularized according to your needs. When an exception is triggered, the log is saved in the file `storage/logs/laravel.log`

## &nbsp;
## Creating Handler
To create your own handler, you can use the `report` method of the `Exceptions` class mentioned above. In this method, you pass a callable (an anonymous function or any other function that can be called) passing the exception you want to handle as a parameter. Example:

```php
//inside withExceptions method
        
$exceptions->report(function (ExampleException $exception) {
    //handle ExampleException
});
```

In the example above, the callable parameter that we pass to the `report` method, we receive as a parameter the exception that we want to handle, within this callable we can do whatever we want with the exception, such as returning a standard response, in this way, every time the exception is triggered anywhere in the code (if it is not inside a try catch block), Laravel will execute the callable that we reported for the exception.

```php
$exceptions->report(function (ExampleException $exception) {

    // default response for all ExampleException triggers
    return response()->json([
        'error' => true,
        'message' => 'An error occurred.',
    ], 500);
});
```

If you want to catch any exception regardless of the class, you can use the `Throwable` interface introduced in PHP 7:

```php
$exceptions->report(function (Throwable $exception) {

    // default response for any exception
    return response()->json([
        'error' => true,
        'message' => 'Internal Server Error.',
    ], 500);
});
```

## &nbsp;
## Saving Logs
If you want to stop laravel from automatically saving logs after throwing an exception and save your own logs you can stop the handling flow and go to the response through the `stop()` method.

```php
$exceptions->report(function (Throwable $exception) {
    // Saving Logs
    Log::error("error: {$exception->getMessage()}", [
        'exception' => $exception->getTraceAsString()
    ]);

    // default response for any exception
    return response()->json([
        'error' => true,
        'message' => 'Internal Server Error.',
    ], 500);
})->stop();
```

It is also possible to stop the handling flow by returning `false` in the report callable.

```php
$exceptions->report(function (Throwable $exception) {
    // Saving Logs
    Log::error("error: {$exception->getMessage()}", [
        'exception' => $exception->getTraceAsString()
    ]);

    return false;
});
```

> In this way, laravel does not execute the "CREATE LARAVEL LOGS" process mentioned previously in the error handling flow image

## &nbsp;

There are some other methods in the `Exceptions` class that can be used in your day to day life. Below you can see a table with the names of the methods and a description of their usefulness in use.

## &nbsp;
> Class: Exceptions

| Method | Utility |
|----------|----------|
| dontReport    | receives an array with all the classes that you don't want to report to log channels   |
| stopIgnoring    | receives an array with all the classes that you want to stop ignoring by default, like http exceptions   |
| render    | receives a callable that uses two parameters, the first being the exception you want to handle and the second parameter being the request received, through this method it is possible to render a frontend page   |

## &nbsp;
> Tip: It is possible to change the default laravel error pages by publishing them from the vendor 
```bash 
php artisan vendor:publish --tag=laravel-errors
```

## &nbsp;
Remember that this article is just a simplified demonstration and with a slightly more informal language so that it can reach as many people as possible, you can view in-depth details of each implementation through the [Official Laravel Documentation](https://laravel.com/docs)