15 мая 2017.
Новостная рассылка
Присоединяйтесь к нашему новостному бюллетеню и не пропускайте новости из мира Laravel, анонсы полезных пакетов и советы опытных разработчиков.

Как отправить email при возникновении ошибки (исключения) в приложении

Автор статьи Amit Gupta Amit Gupta | Learn How to Send an Email on Error Exceptions | Виталий Николенко

Вы создали свое приложение на Laravel, залили все на сервер клиента. И все шло отлично, пока у заказчика не возникли проблемы из-за бага в вашем коде. Он просто закрыл страницу, ошибка повторилась еще и кучи народа, прежде чем вы о ней узнали и исправили.

Знакомая ситуация? А что если бы вы получили сообщение об ошибке по email или другому каналу сразу же при ее возникновении. В Laravel это очень просто реализовать и сейчас мы узнаем как это сделать.

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

/**
 * Отправляем отчет об исключении.
 *
 * Здесь как раз то место, где можно отправить email.
 *
 * @param  \Exception  $exception
 * @return void
 */
public function report(Exception $exception)
{
    if ($this->shouldReport($exception)) {
        $this->sendEmail($exception); // отправляем email
    }

    return parent::report($exception);
}

/**
 * Отправляем email разработчику с уведомлением об ошибке.
 *
 * @param  \Exception  $exception
 * @return void
 */
public function sendEmail(Exception $exception)
{
    // отправка email
}

В коде мы используем метод shouldReport чтобы игнорировать исключения, которые представлены в списке $dontReport обработчика исключений.

Каждый тип сообщений, отправляемый приложением представлен в Laravel своим mailable классом. Создать такой класс можно при помощи команды

 php artisan make:mail ExceptionOccured

Эта команда создаст класс ExceptionOccured в директории app/Mail

Однако, просто уведомления не достаточно. Надо отправить полный стек исключения. Для этого воспользуемся компонентом Symfony Debug

public function sendEmail(Exception $exception)
{
    try {
        $e = FlattenException::create($exception);

        $handler = new SymfonyExceptionHandler();

        $html = $handler->getHtml($e);

        Mail::to('developer@gmail.com')->send(new ExceptionOccured($html));
    } catch (\Exception $ex) {
        dd($ex);
    }
}

Не забудьте добавить вверху файла

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

Обратите внимание, мы завернули отправку сообщения в блок try-catch чтобы избежать бесконечного цикла, если при отправке сообщения возникнет исключение.

Вот так выглядит класс ExceptionOccured

<?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;

    /**
     * The body of the message.
     *
     * @var string
     */
    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);
    }
}

Добавьте следующий код в шаблон  emails.exception

{!! $content !!}

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