Reputation: 7990
I have the following code in my AppServiceprovider::boot
method, whcih ensures I get an email whenever anything is logged with a warning or greater severity level.
$message = \Swift_Message::newInstance( 'An Error has Occurred in XXX' )
->setTo( env('ERROR_EMAIL_TO') )
->setFrom( env('ERROR_EMAIL_FROM') )
->setReplyTo( env('ERROR_EMAIL_REPLY_TO') )
->setContentType( 'text/html' );
$swiftMailer = \Mail::getSwiftMailer();
$handler = new SwiftMailerHandler( $swiftMailer, $message, Logger::WARNING );
$handler->setFormatter( new HtmlFormatter() );
\Log::getMonolog()->pushHandler( $handler );
But while this works, I can't help but feel that it's in the wrong place.
Where would you add this code to a Laravel web app?
Upvotes: 0
Views: 560
Reputation: 2944
How about using middleware? I've written some middleware to log all requests, and responses in the past for APIs that could just as easily dispatch e-mails to inform a user of errors (this was pretty much the use case of why I set it up).
Using the terminate()
method in your middleware class, will allow you to perform logic after a response has been sent to the user - so your e-mails shouldn't slow down the experience for the end user.
namespace App\Http\Middleware;
use Closure;
class LogRequestAndResponseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// Send out an e-mail to you here
}
I think this could be also allow you to a good time to refactor the code, which will help move the logic outside of the middleware and into its own area of responsibility.
In this instance, I'm thinking that I currently want to be informed via e-mail, but I may at some point in the future want to send an event via a Websocket instead.
Therefore, I'd wrap up the logic using a contract and implement it accordingly:
interface ErrorNotificationContract
{
public function inform($user, $message)
}
class EmailErrorNotification implements ErrorNotificationContract
{
protected $mail;
public function __construct(Mail $mail)
{
$this->mail = $mail;
}
public function inform($user, $message)
{
// Your send e-mail logic.
}
}
You can then register this using a service provider. A side effect is that you get the added benefits of:
In your middleware you could then do:
public function terminate($request, $response)
{
// ...
$errorNotifier->inform('[email protected]', 'something bad happened');
}
Upvotes: 2