{{TOC}} {{DOCVER 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51, 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15, 5.1=cdc24ba7426c5b11eb4d050706bd78c3ea4913cc 19.06.2016 20:08:01, 5.0=5d10040a981deee82c0fde0e8e5d2ffc49eaaecb 8.02.2016 18:09:11}} == Введение == Когда вы начинаете новый Laravel проект, обработка ошибок и исключений уже настроена для вас. Все происходящие в вашем приложении исключения записываются в журнал и отображаются пользователю в классе %%(t)App\Exceptions\Handler%%. В этой статье мы подробно рассмотрим этот класс. Для журналирования Laravel использует библиотеку ((https://github.com/Seldaek/monolog Monolog)), которая обеспечивает поддержку различных мощных обработчиков журналов. В Laravel настроены несколько из них, благодаря чему вы можете выбрать между единым файлом журнала, ротируемыми файлами журналов и записью информации в системный журнал. == Настройка == === Детализация ошибок === Параметр %%(conf)debug%% в файле настроек %%(t)config/app.php%% определяет, сколько информации об ошибке показывать пользователю. По умолчанию этот параметр установлен в соответствии со значением переменной среды %%(t)APP_DEBUG%%, которая хранится в файле %%(t).env%%. Для локальной разработки вам следует установить переменную среды %%(t)APP_DEBUG%% в значение %%(t)true%%. **В продакшн-среде эта переменная всегда должна иметь значение %%(t)false%%.** Если значение равно %%(t)true%% на продакшн-сервере, вы рискуете раскрыть важные значения настроек вашим конечным пользователям. === Хранилище журналов === Изначально Laravel поддерживает запись журналов в единый файл (%%(t)single%%), в отдельные файлы за каждый день (%%(t)daily%%), в %%(t)syslog%% и %%(t)errorlog%%. Для использования определённого механизма хранения вам надо изменить параметр %%(conf)log%% в файле %%(t)config/app.php%%. Например, если вы хотите использовать ежедневные файлы журнала вместо единого файла, вам надо установить значение %%(t)log%% равное %%(t)daily%% в файле настроек %%(t)app%%: %% 'log' => 'daily' %% %%(DOCNEW 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51, 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15) **Максимальное число ежедневных файлов журнала** При использовании режима %%(t)daily%% Laravel по умолчанию хранит журналы только за последние 5 дней. Если вы хотите изменить число хранимых файлов, добавьте в файл %%(t)app%% значение для параметра %%(t)log_max_files%%: ~%% 'log_max_files' => 30 ~%% %% %%(DOCNEW 5.3=c06d6a2352ed8c767633aab9c20f2bf7d880c967 28.01.2017 5:00:51, 5.2=6b0b057ae6de3c88cb29188459e38383c622ec23 8.12.2016 23:00:15) === Уровни важности событий === При использовании Monolog сообщения в журнале могут иметь разные уровни важности. По умолчанию Laravel сохраняет в журнал события всех уровней. Но на продакшн-сервере вы можете задать минимальный уровень важности, который необходимо заносить в журнал, добавив параметр %%(conf)log_level%% в файл %%(t)app.php%%. После задания этого параметра Laravel будет записывать события всех уровней начиная с указанного и выше. Например, при %%(conf)log_level%% равном %%(t)error%% будут записываться события **error**, **critical**, **alert** и **emergency**: %%(conf) 'log_level' => env('APP_LOG_LEVEL', 'error'), ~%% .(alert) В Monolog используются следующие уровни важности - от меньшего к большему: %%(t)debug%%, %%(t)info%%, %%(t)notice%%, %%(t)warning%%, %%(t)error%%, %%(t)critical%%, %%(t)alert%%, %%(t)emergency%%. %% **Изменение настроек Monolog** Если вы хотите иметь полный контроль над конфигурацией Monolog для вашего приложения, вы можете использовать метод приложения %%configureMonologUsing()%%. Вызов этого метода необходимо поместить в файл %%(t)bootstrap/app.php%% прямо перед тем, как в нём возвращается переменная %%$app%%: %% $app->configureMonologUsing(function ($monolog) { $monolog->pushHandler(...); }); return $app; %% == Обработчик исключений == === Метод %%report()%% === Все исключения обрабатываются классом %%(t)App\Exceptions\Handler%%. Этот класс содержит два метода: %%report()%% и %%render()%%. Рассмотрим каждый из них подробнее. Метод %%report()%% используется для занесения исключений в журнал или для отправки их во внешний сервис, такой как ((https://bugsnag.com BugSnag)) или ((https://github.com/getsentry/sentry-laravel Sentry)). По умолчанию метод %%report()%% просто передаёт исключение в базовую реализацию родительского класса, где это исключение зафиксировано. Но вы можете регистрировать исключения как пожелаете. Например, если вам необходимо сообщать о различных типах исключений разными способами, вы можете использовать оператор сравнения PHP %%instanceof%%:: %% /** * Сообщить или зарегистрировать исключение. * * Это отличное место для отправки исключений в Sentry, Bugsnag, и т.д. * * @param \Exception $exception * @return void */ public function report(Exception $exception) { if ($exception instanceof CustomException) { // } return parent::report($exception); } %% **Игнорирование исключений заданного типа** Свойство обработчика исключений %%$dontReport%% содержит массив с типами исключений, которые не будут заноситься в журнал. Например, исключения, возникающие при ошибке 404, а также при некоторых других типах ошибок, не записываются в журналы. При необходимости вы можете включить другие типы исключений в этот массив: %% /** * Список типов исключений, о которых не надо сообщать. * * @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-отклик, который должен быть возвращён браузеру. По умолчанию исключение передаётся в базовый класс, который генерирует для вас отклик. Но вы можете проверить тип исключения или вернуть ваш собственный отклик: %% /** * Отрисовка HTTP-оклика для исключения. * * @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); } %% == HTTP-исключения == Некоторые исключения описывают коды HTTP-ошибок от сервера. Например, это может быть ошибка "страница не найдена" (404), "ошибка авторизации" (401) или даже сгенерированная разработчиком ошибка 500. Для возврата такого отклика из любого места в приложении можете использовать вспомогательный метод %%abort()%%: %% abort(404); %% Вспомогательный метод %%abort()%% немедленно создаёт исключение, которое будет отрисовано обработчиком исключений. Или вы можете предоставить такой отклик: %% abort(403, 'Unauthorized action.'); %% === Свои страницы HTTP-ошибок === В Laravel можно легко возвращать свои собственные страницы для различных кодов HTTP-ошибок. Например, для выдачи собственной страницы для ошибки 404 создайте файл %%(t)resources/views/errors/404.blade.php%%. Этот файл будет использован для всех ошибок 404, генерируемых вашим приложением. Представления в этой папке должны иметь имена, соответствующие кодам ошибок. Экземпляр %%(t)HttpException%%, созданный функцией %%abort()%%, будет передан в представление как переменная %%$exception%%. == Журналы == Laravel обеспечивает простой простой уровень абстракции над мощной библиотекой ((http://github.com/seldaek/monolog Monolog)). По умолчанию Laravel настроен на создание файла журнала в %%(t)storage/logs%%. Вы можете записывать информацию в журнал при помощи ((/docs/v5/facades фасада)) %%(t)Log%%: %% User::findOrFail($id)]); } } %% Регистратор событий предоставляет восемь уровней журналирования, описанных в ((https://tools.ietf.org/html/rfc5424 RFC 5424)): **debug**, **info**, **notice**, **warning**, **error**, **critical**, **alert** и **emergency**. %% Log::emergency($message); Log::alert($message); Log::critical($message); Log::error($message); Log::warning($message); Log::notice($message); Log::info($message); Log::debug($message); %% **Контекстная информация** Также в методы журналирования может быть передан массив контекстных данных: %% Log::info('User failed to login.', ['id' => $user->id]); %% **Обращение к низкоуровневому экземпляру Monolog** В Monolog доступно множество дополнительных обработчиков для журналов. При необходимости вы можете получить доступ к низкоуровневому экземпляру Monolog, используемому в Laravel: %% $monolog = Log::getMonolog(); %% %%(DOCNEW 5.0=5d10040a981deee82c0fde0e8e5d2ffc49eaaecb 8.02.2016 18:09:11) Вы также можете зарегистрировать событие для перехвата всех сообщений, передаваемых в журнал. **Регистрация слушателя событий журнала** ~%% Log::listen(function($level, $message, $context) { // }); ~%% %%