Идёт обновление сайта. Несколько дней возможны сбои в оформлении и переводах. Документация работает — если страница выглядит сломанной, обновите её позже.

Документация
L Laravel L intervention/image
Войти
Главная Laravel 10.x Обработка ошибок

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

10.x 7 мар 2026 г.

#Введение

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

#Настройка

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

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

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

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

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

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

use App\Exceptions\InvalidOrderException;

/**
 * Зарегистрировать колбэки обработки исключений для приложения.
 */
public function register(): void
{
    $this->reportable(function (InvalidOrderException $e) {
        // ...
    });
}

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

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

$this->reportable(function (InvalidOrderException $e) {
    return false;
});
Примечание

Для настройки отчётов об исключениях конкретного типа вы также можете использовать отчётные исключения.

#Глобальный контекст логов

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

/**
 * Получить переменные контекста по умолчанию для логирования.
 *
 * @return array<string, mixed>
 */
protected function context(): array
{
    return array_merge(parent::context(), [
        'foo' => 'bar',
    ]);
}

#Контекст логов для исключения

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

<?php

namespace App\Exceptions;

use Exception;

class InvalidOrderException extends Exception
{
    // ...

    /**
     * Получить контекстную информацию исключения.
     *
     * @return array<string, mixed>
     */
    public function context(): array
    {
        return ['order_id' => $this->orderId];
    }
}

#Хелпер report

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

public function isValid(string $value): bool
{
    try {
        // Проверить значение...
    } catch (Throwable $e) {
        report($e);

        return false;
    }
}

#Исключение дублирования отчётов об исключениях

Если вы используете функцию report по всему приложению, иногда одно и то же исключение может быть зарегистрировано несколько раз, создавая дубликаты в логах.

Чтобы гарантировать, что один экземпляр исключения будет зарегистрирован только один раз, установите свойство $withoutDuplicates в true в классе App\Exceptions\Handler вашего приложения:

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    /**
     * Указывает, что экземпляр исключения должен быть зарегистрирован только один раз.
     *
     * @var bool
     */
    protected $withoutDuplicates = true;

    // ...
}

Теперь, когда хелпер report вызывается с одним и тем же экземпляром исключения, будет зарегистрирован только первый вызов:

$original = new RuntimeException('Whoops!');

report($original); // зарегистрировано

try {
    throw $original;
} catch (Throwable $caught) {
    report($caught); // проигнорировано
}

report($original); // проигнорировано
report($caught); // проигнорировано

#Уровни логирования исключений

Когда сообщения записываются в логи вашего приложения, они записываются с указанным уровнем логирования, который отражает важность или серьёзность сообщения.

Как отмечалось выше, даже при регистрации пользовательского колбэка отчёта через метод reportable, Laravel всё равно логирует исключение согласно стандартной конфигурации логирования; однако, поскольку уровень логирования может влиять на каналы, куда отправляется сообщение, вы можете настроить уровень логирования для определённых исключений.

Для этого определите свойство $levels в обработчике исключений вашего приложения. Это свойство должно содержать массив типов исключений и соответствующих им уровней логирования:

use PDOException;
use Psr\Log\LogLevel;

/**
 * Список типов исключений с их пользовательскими уровнями логирования.
 *
 * @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
 */
protected $levels = [
    PDOException::class => LogLevel::CRITICAL,
];

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

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

use App\Exceptions\InvalidOrderException;

/**
 * Список типов исключений, которые не логируются.
 *
 * @var array<int, class-string<\Throwable>>
 */
protected $dontReport = [
    InvalidOrderException::class,
];

Внутренне Laravel уже игнорирует некоторые типы ошибок, например, исключения, связанные с HTTP-ошибками 404 или ответами 419, вызванными недействительными CSRF-токенами. Если вы хотите, чтобы Laravel перестал игнорировать определённый тип исключения, вызовите метод stopIgnoring в методе register вашего обработчика исключений:

use Symfony\Component\HttpKernel\Exception\HttpException;

/**
 * Зарегистрировать колбэки обработки исключений для приложения.
 */
public function register(): void
{
    $this->stopIgnoring(HttpException::class);

    // ...
}

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

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

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

use App\Exceptions\InvalidOrderException;
use Illuminate\Http\Request;

/**
 * Зарегистрировать колбэки обработки исключений для приложения.
 */
public function register(): void
{
    $this->renderable(function (InvalidOrderException $e, Request $request) {
        return response()->view('errors.invalid-order', [], 500);
    });
}

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

use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Зарегистрировать колбэки обработки исключений для приложения.
 */
public function register(): void
{
    $this->renderable(function (NotFoundHttpException $e, Request $request) {
        if ($request->is('api/*')) {
            return response()->json([
                'message' => 'Запись не найдена.'
            ], 404);
        }
    });
}

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

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

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class InvalidOrderException extends Exception
{
    /**
     * Отчёт об исключении.
     */
    public function report(): void
    {
        // ...
    }

    /**
     * Отобразить исключение в HTTP-ответ.
     */
    public function render(Request $request): Response
    {
        return response(/* ... */);
    }
}

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

/**
 * Отобразить исключение в HTTP-ответ.
 */
public function render(Request $request): Response|bool
{
    if (/** Определить, нужно ли кастомное отображение исключения */) {

        return response(/* ... */);
    }

    return false;
}

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

/**
 * Отчёт об исключении.
 */
public function report(): bool
{
    if (/** Определить, нужно ли кастомное отчёт */) {

        // ...

        return true;
    }

    return false;
}
Примечание

Вы можете указывать подсказки типов для любых требуемых зависимостей метода report, и контейнер служб Laravel автоматически внедрит их в метод.

#Ограничение количества отчётов об исключениях

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

Чтобы брать случайную выборку исключений, вы можете вернуть экземпляр Lottery из метода throttle вашего обработчика исключений. Если в классе App\Exceptions\Handler этого метода нет, просто добавьте его:

use Illuminate\Support\Lottery;
use Throwable;

/**
 * Ограничить количество входящих исключений.
 */
protected function throttle(Throwable $e): mixed
{
    return Lottery::odds(1, 1000);
}

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

use App\Exceptions\ApiMonitoringException;
use Illuminate\Support\Lottery;
use Throwable;

/**
 * Ограничить количество входящих исключений.
 */
protected function throttle(Throwable $e): mixed
{
    if ($e instanceof ApiMonitoringException) {
        return Lottery::odds(1, 1000);
    }
}

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

use Illuminate\Broadcasting\BroadcastException;
use Illuminate\Cache\RateLimiting\Limit;
use Throwable;

/**
 * Ограничить количество входящих исключений.
 */
protected function throttle(Throwable $e): mixed
{
    if ($e instanceof BroadcastException) {
        return Limit::perMinute(300);
    }
}

По умолчанию ключом для ограничения используется класс исключения. Вы можете настроить ключ, указав свой с помощью метода by у Limit:

use Illuminate\Broadcasting\BroadcastException;
use Illuminate\Cache\RateLimiting\Limit;
use Throwable;

/**
 * Ограничить количество входящих исключений.
 */
protected function throttle(Throwable $e): mixed
{
    if ($e instanceof BroadcastException) {
        return Limit::perMinute(300)->by($e->getMessage());
    }
}

Разумеется, вы можете возвращать смесь экземпляров Lottery и Limit для разных исключений:

use App\Exceptions\ApiMonitoringException;
use Illuminate\Broadcasting\BroadcastException;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Lottery;
use Throwable;

/**
 * Ограничить количество входящих исключений.
 */
protected function throttle(Throwable $e): mixed
{
    return match (true) {
        $e instanceof BroadcastException => Limit::perMinute(300),
        $e instanceof ApiMonitoringException => Lottery::odds(1, 1000),
        default => Limit::none(),
    };
}

#HTTP-исключения

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

abort(404);

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

Laravel упрощает отображение пользовательских страниц ошибок для различных 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

#Запасные страницы ошибок HTTP

Вы также можете определить "запасную" страницу ошибки для серии HTTP-статусов. Эта страница будет отображаться, если отсутствует страница для конкретного HTTP-кода ошибки. Для этого создайте шаблоны 4xx.blade.php и 5xx.blade.php в директории resources/views/errors вашего приложения.