Обработка ошибок

Содержание:


Введение

При старте нового проекта, ошибки и обработка исключений уже настроена за вас. Исключения запускаются в классе App\Exceptions\Handler, обрабатываются и возвращаются обратно пользователю. Все подробности об этом классе рассмотрим в этой статье.


Конфигурация

Пункт debug в вашем файле конфигурации config/app.php как много информации об ошибке показывается пользователю. По умолчанию, для этого параметра задано значение переменной среды APP_DEBUG, которое располагается в файле .env.

Для локальной разработки, вам стоит установать значение true для переменной среды APP_DEBUG. На сервере, это значение должно быть всегда false. Если вы забыли переключить этот параметр, и на сервере у вас установлено true, вы рискуете показать важную информацию для конечным пользователям.


Обработка исключений

Метод Report

Все расширения обрабатываются в классе App\Exceptions\Handler. Этот класс содержит два метода: report и render. Рассмотрим каждый из них в деталях. Метод report используется для обработки исключению или отправки их сторонним сервисам такаим как Bugsnag или Sentry. По умолчанию, метод report передаёт исключения в базовый класс, в котором ведётся их учёт. Конечно, вы можете вести учёт как считаете нужным.

Например, если вам необходимо информировать о различных видах расширений различными способами, вы можете использовать оператор PHP instanceof:

/**
 * Report or log an exception.
 *
 * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
 *
 * @param  \Exception  $exception
 * @return void
 */
public function report(Exception $exception)
{
    if ($exception instanceof CustomException) {
        //
    }

    parent::report($exception);
}
Вместо того, чтобы делать большое количество проверок в методе report, рассмотрите возможность использовать расширения c встроенной возможностью информирования.

Контекст глобального журнала

Если возможно, Laravel автоматически добавляет идентификатор текущего пользователя в каждую запись журнала, как данные контекста. Вы можете определить ваши глобальные данные контекста путём переписывания метода context класса App\Exceptions\Handler. Эта информация будет включена в каждое сообщение журнала вашего приложения:

/**
 * Get the default context variables for logging.
 *
 * @return array
 */
protected function context()
{
    return array_merge(parent::context(), [
        'foo' => 'bar',
    ]);
}

Помощник report

Иногда вам может потребоваться сделать запись исколючения, но продолжить выполнение текущего запроса. Функция помощник report позволяет вам быстро записать исключение используя метод report без загрузки страницы ошибки:

public function isValid($value)
{
    try {
        // Validate the value...
    } catch (Exception $e) {
        report($e);

        return false;
    }
}

Игнорирование исключений определённого типа

Свойство обработчика исключений $dontReport содержит массив типов исключений, которые не будут добавлены в журнал. Например, исключения в результате ошибок 404, также как и некоторые другие типы ошибок, не записываются в ваш лог-файл. Вы можете добавить и другие типы, если это необходимо:

/**
 * A list of the exception types that should not be reported.
 *
 * @var array
 */
protected $dontReport = [
    \Illuminate\Auth\AuthenticationException::class,
    \Illuminate\Auth\Access\AuthorizationException::class,
    \Symfony\Component\HttpKernel\Exception\HttpException::class,
    \Illuminate\Database\Eloquent\ModelNotFoundException::class,
    \Illuminate\Validation\ValidationException::class,
];

Метод Render

Метод render отвечает за преобразование исключения обратно в ответ HTTP, который высылает в браузер. По умолчанию, исключение передаётся в базовый класс, который генерирует ответ. По желанию, вы можете легко проверить тип исключения или вернуть ваш собственный ответ:

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $exception
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $exception)
{
    if ($exception instanceof CustomException) {
        return response()->view('errors.custom', [], 500);
    }

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

Исключения Reportable и Renderable

Вместо проверки типов исключений в обработчиках report и render, вы можете определить методы report и render напрямую, в вашем пользовательском исключении. При наличии этих методов, они автоматически будут запущены фреймворком:

namespace App\Exceptions;

use Exception;

class RenderException extends Exception
{
    /**
     * Report the exception.
     *
     * @return void
     */
    public function report()
    {
        //
    }

    /**
     * Render the exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request
     * @return \Illuminate\Http\Response
     */
    public function render($request)
    {
        return response(...);
    }
}
Вы можете вписывать любые зависимости метода report, они будут автоматически внедрены в метод через сервис контейнер Ларавел.

Исключения HTTP

Некоторые исключения описывают коды ошибки HTTP со стороны сервера. Например, это может быть "страница не найдена" ошибка (404), "ошибка авторизации" (401), или даже сгенерированная разработчиком ошибка 500. Чтобы сгенерировать такой ответ из любоай точки приложения, вы можете использовать помощник abort:

abort(404);

Помощник abort немедленно вызовет исключение, которое будет отображено обработчиком исключений. При необходимости вы можете указать текст ответа:

abort(403, 'Unauthorized action.');

Пользовательские страницы ошибок HTTP

Laravel делает лёгким отображение пользовательских страниц ошибки для большого количества статус кодов HTTP. Например, если вы хотите настроить страницу ошибки для статуса HTTP 404, создайте файл resources/views/errors/404.blade.php. Этот файл будет открываться для каждой ошибки 404 вашего приложения. Все представления в этой папке должны быть названы как сответсвующий HTTP статус код. Экземпляр HttpException вызывается функцией abort и будет передан в представление как переменная $exception:

{{ $exception->getMessage() }}

Вы можете опубликовать шаблон страницы ошибки Laravel используя команду Artisan vendor:publish. После публикации, вы можете настраивать его как вам угодно:

php artisan vendor:publish --tag=laravel-errors