Laravel Error Handling

In this tutorial we will learn how can we handle different types of errors using laravel framework. When you are working on web or rest api it is very crucial to learn how to handle errors well.

Laravel gives you so much flexibility when it comes to error handling I am sure you would learn something new here in this tutorial. You can override any of the laravel status code template.

Let's first learn different types of http responses and related codes.

Http Response Codes and Statuses

Code Status Description
200 Ok The request was successfully completed.
201 Created A new reesource was successfully created.
400 Bad Request The request was invalid.
401 Unauthorized Invalid login credentials.
403 Forbidden You do not have enough permissions to perform this action.
404 Not Found The requested resource/page not found.
405 Method Not Allowed This request is not supported by the resource.
409 Conflict The request could not be completed due to a conflict.
500 Internal Server Error The request was not completed due to an internal error on the server side.
503 Service Unavailable The server was unavailable.

Above are some of the popular http responses and their related codes you can change the description according to your requirement. Let's say you want to create a custom html page for above status codes in laravel.

You simply create following files and modify the content of the file as per your requirements:

resources
    |-- views
          |-- errors
                |-- 404.blade.php
                |-- 401.blade.php
                |-- 403.blade.php
                |-- 500.blade.php

You have to follow the file structure as mentioned above otherwise you will not be able to override above error pages. To get the error message in the view file you can use following variable in your blade view:

# 404.blade.php
<h2>{{ $exception->getMessage() }}</h2>

How to catch and render custom exception view/message in laravel?

Let say that you want to create a custom response or view for your custom error you can do that in laravel. All you need to do is to modify  App\Exceptions\Handler class.

Let say you have setup laravel rest api and now want to render json error instead of html error in your laravel app for all routes that starts with /api prefix. Open App\Exceptions\Handler class and mondify render function as shown below:

<?php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Illuminate\Http\Request;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'current_password',
        'password',
        'password_confirmation',
    ];

    /**
     * Register the exception handling callbacks for the application.
     *
     * @return void
     */
    public function register()
    {
        $this->reportable(function (Throwable $e) {
            return false;
        });
    }

    /**
     * @param Request $request
     * @param Throwable $e
     * @return JsonResponse|Response|\Symfony\Component\HttpFoundation\Response
     * @throws Throwable
     */
    public function render($request, Throwable $e)
    {
        if ($request->is('api/*')) {
            return response()->json([
                'message' => 'Record not found.'
            ], 404);
        }

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

Hope you got my point here basically we are overriding parent function and added some additional logic to fit our requirements. You can add some other custom logic here to meet your exception requirements.

Error handling using register method

You can also render different error page using laravel register method inside your App\Exceptions\Handler class. Let's take an example let's create a new exception class that will be called when order fails in our app.

To generate new exception class follow the command below:

php artisan make:exception InvalidOrderException

Above command will create a file under app/Exceptions folder with name InvalidOrderException.php. Let's open this new file and modify as shown below:

<?php

namespace App\Exceptions;

use Exception;

class InvalidOrderException extends Exception
{
    /**
     * Get the exception's context information.
     *
     * @return array
     */
    public function context(): array
    {
        return ['order_id' => 123];
    }
}

We added this new function called context which returns array you can add any custom key which you can later use in the template file. Let's modify our  App\Exceptions\Handler class as shown below:

<?php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Illuminate\Http\Request;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'current_password',
        'password',
        'password_confirmation',
    ];

    /**
     * Register the exception handling callbacks for the application.
     *
     * @return void
     */
    public function register()
    {
        $this->renderable(function (InvalidOrderException $e, $request) {
            return response()->view('errors.invalid-order', [], 500);
        });
    }
}

Now, create a file called invalid-order.php under app/resources/views/errors folder and modify the content of the file according to your need. Hope you enjoyed this tutorial stay tune for more tutorials on laravel.