Skip to content
Icon

ПРЕДУПРЕЖДЕНИЕ Вы просматриваете документацию к старой версии Laravel. Рассмотрите возможность обновления Вашего проекта до Laravel 9.x.

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

Введение

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

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

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

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

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

Отчет об исключениях

Все исключения обрабатываются классом App\Exceptions\Handler. Этот класс содержит метод register, в котором вы можете зарегистрировать пользовательские отчеты об исключениях и обратные вызовы рендеринга. Мы подробно рассмотрим каждую из этих концепций. Отчеты об исключениях используются для регистрации исключений или отправки их во внешнюю службу, например, Flare, Bugsnag или Sentry. По умолчанию исключения будут регистрироваться в соответствии с вашей конфигурацией logging. Однако вы можете регистрировать исключения, как хотите.

Например, если вам нужно сообщать о различных типах исключений по-разному, вы можете использовать метод reportable для регистрации замыкания, которое должно выполняться, когда необходимо сообщить об исключении данного типа. Laravel определит, о каком типе исключения сообщает замыкание, изучив подсказку типа замыкания:

use App\Exceptions\InvalidOrderException;
 
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (InvalidOrderException $e) {
//
});
}

Когда вы регистрируете пользовательский обратный вызов для создания отчетов об исключениях, используя метод reportable, по-прежнему будет регистрировать исключение, используя конфигурацию ведения журнала по умолчанию для приложения. Если вы хотите остановить распространение исключения в стек журналов по умолчанию, вы можете использовать метод stop при определении обратного вызова отчета или вернуть false из обратного вызова:

$this->reportable(function (InvalidOrderException $e) {
//
})->stop();
 
$this->reportable(function (InvalidOrderException $e) {
return false;
});

{tip} Чтобы настроить отчет об исключениях для данного исключения, вы также можете использовать отчетные исключения.

Глобальный контекст журнала

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

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

Контекст журнала исключений

Хотя добавление контекста в каждое сообщение журнала может быть полезным, иногда конкретное исключение может иметь уникальный контекст, который вы хотели бы включить в свои журналы. Определив метод context для одного из настраиваемых исключений вашего приложения, вы можете указать любые данные, относящиеся к этому исключению, которые должны быть добавлены в запись журнала исключения:

<?php
 
namespace App\Exceptions;
 
use Exception;
 
class InvalidOrderException extends Exception
{
// ...
 
/**
* Get the exception's context information.
*
* @return array
*/
public function context()
{
return ['order_id' => $this->orderId];
}
}

Помощник report

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

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

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

При создании приложения будут некоторые типы исключений, которые вы просто хотите игнорировать и никогда не сообщать. Обработчик исключений вашего приложения содержит свойство $dontReport, которое инициализируется пустым массивом. Ни о каких классах, которые вы добавляете в это свойство, никогда не будет сообщено; однако у них все еще может быть настраиваемая логика рендеринга:

use App\Exceptions\InvalidOrderException;
 
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
InvalidOrderException::class,
];

{tip} За кулисами Laravel уже игнорирует некоторые типы ошибок, такие как исключения, возникающие из-за ошибок 404 HTTP «не найден» или 419 ответов HTTP, сгенерированных недопустимыми токенами CSRF.

Рендеринг исключений

По умолчанию обработчик исключений Laravel преобразует исключения в HTTP-ответ за вас. Однако вы можете зарегистрировать настраиваемое замыкание отрисовки для исключений данного типа. Вы можете сделать это с помощью метода renderable вашего обработчика исключений.

Замыкание, переданное методу renderable, должно возвращать экземпляр Illuminate\Http\Response, который может быть сгенерирован с помощью помощника response. Laravel определит, какой тип исключения рендерит замыкание, изучив подсказку типа замыкания:

use App\Exceptions\InvalidOrderException;
 
/**
* 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);
});
}

Вы также можете использовать метод renderable, чтобы переопределить поведение рендеринга для встроенных исключений Laravel или Symfony, таких как NotFoundHttpException. Если закрытие, данное методу renderable, не возвращает значение, будет использоваться рендеринг исключений Laravel по умолчанию:

use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->renderable(function (NotFoundHttpException $e, $request) {
if ($request->is('api/*')) {
return response()->json([
'message' => 'Record not found.'
], 404);
}
});
}

Отчетные и отображаемые исключения

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

<?php
 
namespace App\Exceptions;
 
use Exception;
 
class InvalidOrderException extends Exception
{
/**
* Report the exception.
*
* @return bool|null
*/
public function report()
{
//
}
 
/**
* Render the exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function render($request)
{
return response(...);
}
}

Если ваше исключение расширяет исключение, которое уже может быть отображено, например, встроенное исключение Laravel или Symfony, вы можете вернуть false из метода render исключения, чтобы отобразить HTTP-ответ исключения по умолчанию:

/**
* Render the exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function render($request)
{
// Determine if the exception needs custom rendering...
 
return false;
}

Если ваше исключение содержит настраиваемую логику отчетов, которая необходима только при выполнении определенных условий, вам может потребоваться указать Laravel иногда сообщать об исключении, используя конфигурацию обработки исключений по умолчанию. Для этого вы можете вернуть false из метода исключения report:

/**
* Report the exception.
*
* @return bool|null
*/
public function report()
{
// Determine if the exception needs custom reporting...
 
return false;
}

{tip} Вы можете указать любые требуемые зависимости метода report, и они будут автоматически добавлены в метод сервисным контейнером.

Исключения HTTP

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

abort(404);

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

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

<h2>{{ $exception->getMessage() }}</h2>

Вы можете опубликовать стандартные шаблоны страниц ошибок Laravel с помощью Artisan-команды vendor:publish. После публикации шаблонов вы можете настроить их по своему вкусу:

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