Отправка сообщения на почту при возникновении исключения (сайты на Laravel)

Данный материал является вольным переводом статьи «Learn How to Send an Email on Error Exceptions» с сайта laravel-news.com (автор статьи Amit Gupta). 

В Laravel все исключения обрабатываются классом App\Exceptions\Handler. Этот класс содержит два метода: report() и render(). Нас интересует метод report(). Он используется для отправки сообщений об ошибках в логи или на внешние сервисы, такие как Bugsnag или Sentry. По умолчанию метод report() передает сообщение об ошибке базовому классу, который создает запись в лог-файле. Тем не менее, мы можем использовать данный метод для отправки сообщения об ошибке разработчику на почту. 

Прежде всего, создадим новый проект. После чего откроем файл Handler.php (папка app/Exceptions). 

Перепишем метод report() следующим образом:

public function report(Exception $exception)
{
    if ($this->shouldReport($exception)) {
        $this->sendEmail($exception);
    }
    return parent::report($exception);
}

Здесь мы используем метод shouldReport() для игнорирования типов исключений, указанных в массиве $dontReport. По умолчанию содержимое массива следующее:

protected $dontReport = [
    \Illuminate\Auth\AuthenticationException::class,
    \Illuminate\Auth\Access\AuthorizationException::class,
    \Symfony\Component\HttpKernel\Exception\HttpException::class,
    \Illuminate\Database\Eloquent\ModelNotFoundException::class,
    \Illuminate\Session\TokenMismatchException::class,
    \Illuminate\Validation\ValidationException::class,
];

Далее, в конец файла, добавим метод sendEmail() со следующим содержимым:

public function sendEmail(Exception $exception)
{
    try {
        $e = FlattenException::create($exception);
        $handler = new SymfonyExceptionHandler();
        $html = $handler->getHtml($e);
        Mail::to('[email protected]')->send(new ExceptionOccured($html));
    } catch (Exception $ex) {
        dd($ex);
    }
}

Здесь мы использовали try-блок, чтобы отловить возможную неудачу при отправке email-сообщения. Также мы использоввали класс ExceptionHandler компонента symfony/debug для получения всего списка методов, которые были вызваны до момента возникновения исключения (stack trace). 

Далее в начало файла добавим следующий код:

use Mail;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\Debug\ExceptionHandler as SymfonyExceptionHandler;
use App\Mail\ExceptionOccured;

Для создания email-сообщения мы будем использовать отдельный класс ExceptionOccured. Создадим его, используя команду:

php artisan make:mail ExceptionOccured

Откроем созданный класс (папка app/Mail). Добавим туда следующее содержимое (выделено жирным):

<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class ExceptionOccured extends Mailable
{
    use Queueable, SerializesModels;
    public $content;
    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($content)
    {
        $this->content = $content;
    }
    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.exception')->with('content', $this->content);
    }
}

В методе build() мы передаем в вид emails.exception переменную $content, содержащую информацию об исключении. 

Осталось создать нужный вид (/resources/views/emails/exception.blade.php) и добавить туда следующий код:

{!! $content !!}

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