Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Журнал и обработка ошибок

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

Запись в журнал

use Illuminate\Support\Facades\Log;
 
Log::info('Пользователь вошёл', ['user_id' => $user->id]);
 
Log::warning('Оплата прошла со второй попытки', ['order_id' => $order->id]);
 
Log::error('Платёжный сервис недоступен');

Второй аргумент — массив с подробностями. По умолчанию сообщения попадают в файл storage/logs/laravel.log.

Уровни

УровеньКогда использовать
debugПодробности для отладки
infoОбычные события: вход, заказ
warningЧто-то необычное, но работа продолжается
errorОперация не удалась
criticalОтказ важной части системы

Переменная LOG_LEVEL в .env задаёт наименьший уровень, который записывается. На рабочем сервере обычно ставят warning или error.

Каналы

Канал определяет, куда уходят сообщения. Они описаны в config/logging.php:

КаналЧто делает
singleОдин файл
dailyНовый файл на каждый день, старые удаляются
stackНесколько каналов сразу
slackСообщения в чат Slack
LOG_CHANNEL=daily
LOG_LEVEL=warning

Сообщение можно отправить в конкретный канал: Log::channel('slack')->critical('Сайт недоступен').

Как Laravel обрабатывает ошибки

Непойманное исключение Laravel перехватывает сам: записывает в журнал и возвращает ответ. При APP_DEBUG=true это подробная страница с кодом и стеком вызовов, при false — простая страница «Ошибка сервера».

Свои страницы ошибок

Создайте шаблон с именем кода ошибки в папке resources/views/errors:

{{-- resources/views/errors/404.blade.php --}}
<x-layout>
    <h1>Страница не найдена</h1>
    <p>Возможно, она была удалена или адрес введён с ошибкой.</p>
    <a href="/">На главную</a>
</x-layout>

Так же делают 403.blade.php, 500.blade.php, 503.blade.php.

Вызов ошибки

abort(404);
 
abort_if(!$user->is_admin, 403);
 
abort_unless($post->is_published, 404, 'Статья не опубликована');

Метод findOrFail() сам вызывает ошибку 404, если запись не найдена.

Настройка обработки

Поведение для конкретных исключений задают в файле bootstrap/app.php:

use App\Exceptions\PaymentFailed;
 
->withExceptions(function (Exceptions $exceptions) {
    $exceptions->report(function (PaymentFailed $e) {
        Log::channel('slack')->error($e->getMessage());
    });
 
    $exceptions->render(function (PaymentFailed $e, Request $request) {
        return response()->view('errors.payment', status: 402);
    });
})

report() определяет, как записать исключение, render() — что показать пользователю.

Частая ошибка

В журнал нельзя писать пароли, номера карт, токены. Файл журнала читают разработчики и служба поддержки, его отправляют в сторонние сервисы. Записывайте идентификаторы — user_id, order_id, — а не сами данные. И не оставляйте LOG_LEVEL=debug на рабочем сервере: журнал вырастет до гигабайтов.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.