Learning Management Platform for Written Tutorial Series.

Laravel 5 Exception Handling

Laravel 5 Exception Handling

Introduction

Anything that can go wrong will go wrong. Anything that cannot go wrong will still go wrong anyway. Exception handling allows our app to gracefully handle exceptions when they ago. At times we may need to throw exceptions on purpose then catch them.

In this tutorial, we are going to learn about exception handling in Laravel and how the framework handles exceptions when they are thrown.

We will also look at third party packages such as sentry that will send you an email notification whenever an exception handles in your application. We will also look at PHPDebugbar and how to integrate it into Laravel.

By the end of this tutorial, you would have known how to throw and handle exception

The following screen shots shows you what you will build by the end of this tutorial.

Laravel Sentry Exceptions

Laravel Exception Handling

Topics to be covered

In this tutorial, we will cover the following topics

  • Tutorial prerequisites
  • Tutorial Starter Code
  • Laravel Exception Handling Basics
  • Laravel PHP Debug Bar
  • Integrating Laravel with Sentry
  • Larashop Admin Panel Exception Handling
  • Complete Tutorial Code

Tutorial prerequisites

This tutorial assumes;

  • You understand the basics of Laravel 5. If you do then I recommend you start with these Laravel 5 Tutorial series.
  • You have PHP, MySQL and a web server i.e. Apache up and running
  • Laravel Homestead – this is optional but provides a great development environment. If you are new to Laravel homestead then I recommend you read the series on Laravel Homestead
  • You have composer installed
  • You have a text editor or IDE that supports PHP.
  • You have a modern web browser that supports HTML5
  • Git – this is optional but highly recommended. This tutorial has a repository on GitHub, with Git, you will be able to clone starter code for each tutorial.

Tutorial Starter Code

This tutorial builds on from the previous tutorial. If you have not been following the tutorial series, then you can download starter code for this tutorial from GitHub

If you have git installed, run the following command to clone the project

git clone -b 05_validation https://github.com/KodeBlog/Laradmin.git laradmin

HERE,

  • git clone -b 05_validation clones the branch laradmin from the repository https://github.com/KodeBlog/Laradmin.git into a local folder laradmin.

Laravel Exception Handling Basics

Laravel has built in mechanisms for handling exception when they occur. By default, exceptions are handled by the /app/Exceptions/Handler.php

An exception can be thrown when a user tries to access a resource that does not exists, the application requests an object that does not exists or when a user tries to access a resource that they are not authorized to access.

In such cases, Laravel throws an exception that is handled by the Exception Handler class. The thrown exception is accompanied by a relevant HTTP code. For example, 404 is for resource not found, 401 unauthorized access while 500 is generally for internal server errors such as failed database connection or trying to load a class that does not exist.

Let’s start with a very basic exception.

Fire up our app with the following artisan command

php artisan serve –port=8888

we will deliberately try to access route that we know does not exist

Try the following URL

http://localhost:8888/hades

You will get the following message

Sorry, the page you are looking for could not be found.

If you open the developer tools by pressing F12, you will not that the response is returned with a 404 error code. Laravel custom 404 error page.

Let’s now look at how you can customize the route not found exception. We want to display a custom page when that happens.

Create a new view 404.blade.php in /resources/views/errors/

Add the following code to 404.blade.php

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <!-- Meta, title, CSS, favicons, etc. -->
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Requested resource not found</title>
        <!-- Bootstrap -->
        <link href="{{asset('admin/css/bootstrap.min.css')}}" rel="stylesheet">
        <!-- Font Awesome -->
        <link href="{{asset('admin/css/font-awesome.min.css')}}" rel="stylesheet">
        <!-- NProgress -->
        <link href="{{asset('admin/css/nprogress.css')}}" rel="stylesheet">
        <!-- Custom Theme Style -->
        <link href="{{asset('admin/css/custom.min.css')}}" rel="stylesheet">
    </head>
    <body class="nav-md">
        <div class="container body">
            <div class="main_container">
                <!-- page content -->
                <div class="col-md-12">
                    <div class="col-middle">
                        <div class="text-center text-center">
                            <h1 class="error-number">404</h1>
                            <h2>Sorry but we couldn't find this page</h2>
                            <p>This page you are looking for does not exist <a href="#">Report this?</a>
                        </p>
                        <div class="mid_center">
                            <h3>Search</h3>
                            <form>
                                <div class="col-xs-12 form-group pull-right top_search">
                                    <div class="input-group">
                                        <input type="text" class="form-control" placeholder="Search for...">
                                        <span class="input-group-btn">
                                            <button class="btn btn-default" type="button">Go!</button>
                                        </span>
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
            <!-- /page content -->
        </div>
    </div>
    <!-- jQuery -->
    <script src="{{asset('admin/js/jquery.min.js')}}"></script>
    <!-- Bootstrap -->
    <script src="{{asset('admin/js/bootstrap.min.js')}}"></script>
    <!-- FastClick -->
    <script src="{{asset('admin/js/fastclick.js')}}"></script>
    <!-- NProgress -->
    <script src="{{asset('admin/js/nprogress.js')}}"></script>
    <!-- Custom Theme Scripts -->
    <script src="{{asset('admin/js/custom.min.js')}}"></script>
</body>
</html>

HERE,

  • The above contains the markup for the 404 error from the template that we are using to create our admin panel.

We will now modify the exception handler’s render method so that we can display the custom error message that corresponds to our response status code.

Add the following line to render method just before the return statement if($exception instanceof NotFoundHttpException) { return response()->view('errors.404', [], 404); }

HERE,

  • The above code checks if the instance of the variable is NotFoundHttpException. If it is true, it returns the view we defined in /resources/errors/404.blade.php. if it is false, the parent render method is executed which will return the default Laravel error page.

Try to access the above URL that does not exists

You should be able to get something similar to the following

Laravel 404 error

What just happened? How did we get the above results? It is quite simple actually, Laravel threw a NotFoundHttpException and we added custom code to the exception handler that displays a special view 404.blade.php whenever the exception NotFoundHttpException is thrown.

Laravel custom internal server error page

When errors occur, we usually don’t display the exception message to the user. we want to display a general purpose error message that informs the user something has gone wrong and we are working on it.

For a NotFoundHttpException exception, we already have a custom view for it. We will now create a 500.blade.php template that will be displayed whenever any exception that doesn’t have a special view occurs.

Create a new view 500.blade.php in /resources/views/errors/500.blade.php

Replace the code with the following

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <!-- Meta, title, CSS, favicons, etc. -->
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Internal Server Error</title>
        <!-- Bootstrap -->
        <link href="{{asset('admin/css/bootstrap.min.css')}}" rel="stylesheet">
        <!-- Font Awesome -->
        <link href="{{asset('admin/css/font-awesome.min.css')}}" rel="stylesheet">
        <!-- NProgress -->
        <link href="{{asset('admin/css/nprogress.css')}}" rel="stylesheet">
        <!-- Custom Theme Style -->
        <link href="{{asset('admin/css/custom.min.css')}}" rel="stylesheet">
    </head>
    <body class="nav-md">
        <div class="container body">
            <div class="main_container">
                <!-- page content -->
                <div class="col-md-12">
                    <div class="col-middle">
                        <div class="text-center">
                            <h1 class="error-number">500</h1>
                            <h2>Internal Server Error</h2>
                            <p>We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing. <a href="#">Report this?</a>
                        </p>
                        <div class="mid_center">
                            <h3>Search</h3>
                            <form>
                                <div class="col-xs-12 form-group pull-right top_search">
                                    <div class="input-group">
                                        <input type="text" class="form-control" placeholder="Search for...">
                                        <span class="input-group-btn">
                                            <button class="btn btn-default" type="button">Go!</button>
                                        </span>
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
            <!-- /page content -->
        </div>
    </div>
    <!-- jQuery -->
    <script src="{{asset('admin/js/jquery.min.js')}}"></script>
    <!-- Bootstrap -->
    <script src="{{asset('admin/js/bootstrap.min.js')}}"></script>
    <!-- FastClick -->
    <script src="{{asset('admin/js/fastclick.js')}}"></script>
    <!-- NProgress -->
    <script src="{{asset('admin/js/nprogress.js')}}"></script>
    <!-- Custom Theme Scripts -->
    <script src="{{asset('admin/js/custom.min.js')}}"></script>
</body>
</html>

Let’s make our application fail on purpose. Change the database name from laradmin to laradminx

Try to access the following URL

localhost:8888/admin/brands

You will get the following error message

Laravel 500 error

Laravel PHP Debug Bar

PHP Debug Bar provides when useful information that viewing the application from the web browser. Take a look at the following image

Laravel PHP Debugbar

The above image shows PHP Debug Bar in action. We have messages, timeline, exceptions, views, routes etc. that provide information about our application. This useful is very useful when debugging and optimizing the application.

In this section, we are going to use composer to add PHP Debug Bar to our application.

Run the following composer command

composer require barryvdh/laravel-debugbar

After the installing has been completed successfully, you need to add the service provider to /config/app.php

Add the following to the providers array

Barryvdh\Debugbar\ServiceProvider::class,

Add the following to the aliases array

'Debugbar' => Barryvdh\Debugbar\Facade::class,

Let’s now publish the configuration file by running the following command

php artisan vendor:publish --provider="Barryvdh\Debugbar\ServiceProvider"

That is it, you are good to go. As long as your application is set to debug mode .env, you will be able to see the Debugbar at the bottom of the application when you load it from the web browser. If any exceptions occur, the information will be displayed in the exceptions section of the debugbar

Integrating Laravel with Sentry

Another useful tool that we need to cover in this tutorial is sentry. This tool is very helpful when the code is in production mode. Sentry will notify you via email whenever an error occurs in your application. The following image shows the sample notifications  

You can try sentry for free. You can sign up for an account from the official sentry website.

Run the following composer command to install the package into our admin panel

composer require sentry/sentry-laravel

Let’s now add the service provider and alias to /config/app.php file

Add the following line to the providers array

Sentry\SentryLaravel\SentryLaravelServiceProvider::class,

Add the following entry to the aliases array

'Sentry' => Sentry\SentryLaravel\SentryFacade::class,

Let’s now publish the config file by running the following command

php artisan vendor:publish --provider="Sentry\SentryLaravel\SentryLaravelServiceProvider"

We will now need to add a new entry to .env file that contains the DNS for sentry. You will get the DNS sentry value from your account after signing up on sentry.io

SENTRY_DSN=https://public:secret@sentry.example.com/1

HERE,

  • Replace https://public:secret@sentry.example.com/1 with the value that corresponds to your repository on sentry

The final step is to configure the Handler class to communicate with sentry whenever an error occurs.

Add the following line to the report method of /app/Exceptions/Handler.php

if ($this->shouldReport($exception)) {
    app('sentry')->captureException($exception);
}

Save the changes

Larashop Admin Panel Exception Handling

Now that we have covered the basics of exception handling in Laravel, let’s look at how we can apply this knowledge in our application. We will make a few changes to our controllers. Suppose that the user tries to access a resource that does not exist. For example, a user tries to access /admin/brands/33/edit but the id 33 does it exists in the brands table. We should be able to respond with the appropriate 404 error message.

The code for showing the editing form should be as follows

public function edit($id)
{
    try
    {
        $brand = Brand::findOrFail($id);

        $params = [
            'title' => 'Edit Brand',
            'brand' => $brand,
        ];

        return view('admin.brands.brands_edit')->with($params);
    }
    catch (ModelNotFoundException $ex) 
    {
        if ($ex instanceof ModelNotFoundException)
        {
            return response()->view('errors.'.'404');
        }
    }
}

HERE,

  • try{…}catch() is the good ol’ PHP exception handling block.
  • $brand = Brand::findOrFail($id); attempts to find the record with the id $id and throws an a ModelNotFoundException exception if the record is not found.
  • catch (ModelNotFoundException $ex) responds to ModelNotFoundException exception and displays the view in /resources/views/errors/404.blade.php

The above logic has been applied on all controller methods that deal with retrieving data.

We will not paste the code for all the controllers. Take your time to go through the tutorial project files which you can download here or browser on the official GitHub repository.

Complete Tutorial Code

The complete code for this tutorial can be cloned from the following branch

git clone -b 06_exception_handling https://github.com/KodeBlog/Laradmin.git laradmin

Run the following command to browser to the root of the project

cd laradmin

We will now use composer to install dependencies.

composer install

When the installation is completed, run the following artisan command

php artisan serve

Summary

Exception handling allows us to gracefully respond to exceptions when they occur in our applications. We can take advantage of tools such as PHPDebugbar and sentry to monitor the exceptions and attend to them as we get real-time notifications

What’s next?

The next tutorial will be on Laravel Authentication with password reset.

Kode Blog Tutorials is dedicated to bring you update to date, high quality free tutorials. You can support us by using the social media buttons to like and share the tutorial and subscribing to our newsletter. Please use the comments section below to give us feedback.

Each week, a new Laravel tutorial is added to our collection. Subscribe to our newsletter, like our Facebook fan page or follow us on Twitter to get free updates when the collection is updated.


...