Applications fail due to bad quality coding or just because you forgot to catch some code that wasn't supposed to fail at all. Whatever the reason is, you will obviously want to know when this happens to apply a counter measure. In symfony 1.4 there's a pretty easy way to do it attaching some action to the event dispatcher.
In this article, we will explain you briefly how to report exceptions of your Symfony 1.4 application via email automatically.
1. Create plugin structure
Inside the plugins directory, you will need to create a directory with the name of the plugin namely sfErrorEmailNotifierPlugin
. Inside this directory you will create 2 directories with 2 classes as the following list shows:
- sfErrorEmailNotifierPlugin
- config
sfErrorEmailNotifierPluginConfiguration.class.php
- lib
sfErrorEmailNotifierPlugin.php
- config
We will provide you with the content of every class on the next steps, the important step by now is to create the directory with the mentioned structure (yourproject/plugins
).
2. Create notification class
The sfErrorEmailNotifier
class will contain the code that will be executed when an unhandled exception is thrown on your application. The dispatcher that will be connected to the application.throw_exceptions
event of the application, will trigger the defined static function in the specified class. In our case, we will have a method namely notify that receives as first argument an sfEvent
object and it will basically manipulate the event to extract the error information and send an email with it:
<?php
/**
* This class notifies via Email details about exceptions on the application.
*
* @package symfony
* @subpackage plugin
* @author Carlos Delgado <[email protected]>
*/
class sfErrorEmailNotifier {
static public function notify(sfEvent $event) {
$email = "[email protected]";
$passwordEmail = "12345";
$date = date('d/m/Y H:i:s');
$exception = $event->getSubject();
$context = sfContext::getInstance();
$env = 'n/a';
if ($conf = sfContext::getInstance()->getConfiguration()) {
$env = $conf->getEnvironment();
}
// The notification should be sent only in production mode, not in development environment
if($env == "prod"){
try{
$data = array();
$data['className'] = get_class($exception);
$data['message'] = !is_null($exception->getMessage()) ? $exception->getMessage() : 'n/a';
$data['moduleName'] = $context->getModuleName();
$data['actionName'] = $context->getActionName();
$data['uri'] = $context->getRequest()->getUri();
$data['line'] = $exception->getLine();
$data['file'] = $exception->getFile();
$subject = "Unhandled exception: {$_SERVER['HTTP_HOST']} Exception - $env - {$data['message']}";
// 1. Build email HTML
$emailContent = <<<EOF
<h1>Automatic error report in your application</h1>
<p>Date: {$fecha}</p>
<br>
<p>Subject: <b>{$subject}</b></p>
<br>
<p>An exception has been registered on the production environment, details as follow:</p>
<ul>
<li>Exception type: <b>{$data['className']}</b></li>
<li>Message: <b>{$data['message']}</b></li>
</ul>
<p>The exception was thrown in:</p>
<ul>
<li>URI: <b>{$data['uri']}</b></li>
<li>Module: <b>{$data['moduleName']}</b></li>
<li>Action: <b>{$data['actionName']}</b></li>
<li>File: <b>{$data['file']}</b></li>
<li>Line: <b>{$data['line']}</b></li>
</ul>
EOF;
// 2. Send email
// The transport message configuration may change according to your email service
$transport = \Swift_SmtpTransport::newInstance('smtp.mailserver.com', 465, 'ssl')
->setUsername($email)
->setPassword($passwordEmail);
$mailer = \Swift_Mailer::newInstance($transport);
$message = \Swift_Message::newInstance("Automatic error report in {$nombreAplicacion}")
->setFrom(array(
$email => 'Automatic error report'
))
->setTo(array(
"[email protected]" => "[email protected]"
))
->setBody($emailContent, 'text/html');
// Enviar mail
$mailer->send($message);
}catch(Exception $e){}
}
}
}
3. Create plugin configuration class
Now that you have the code to send emails, you need to create a configuration class that will initialize the plugin when we register it later, the content of the sfErrorEmailNotifierPluginConfiguration.class.php
will be the following (yourproject/plugins/sfErrorEmailNotifierPlugin/config/sfErrorEmailNotifierPluginConfiguration.class.php
):
<?php
/**
* Plugin configuration.
*
* @package symfony
* @subpackage sfErrorEmailNotifier
* @author Carlos Delgado <[email protected]>
*/
class sfErrorEmailNotifierPluginConfiguration extends sfPluginConfiguration {
public function initialize() {
// Registrar a evento global de reporte de errores
$this->dispatcher->connect('application.throw_exception', array('sfErrorEmailNotifier', 'notify'));
}
}
4. Enable Plugin
Finally, to enable the created plugin you need to add it to the application using the enablePlugins
method in your sfProjectConfiguration
class (yourproject/config/ProjectConfiguration.class.php
):
<?php
require_once dirname(__FILE__) . '/../symfony-1.4.27/lib/autoload/sfCoreAutoload.class.php';
sfCoreAutoload::register();
class ProjectConfiguration extends sfProjectConfiguration {
public function setup() {
// 1. Enable plugin
$this->enablePlugins(array(
'sfErrorEmailNotifierPlugin'
));
}
}
After saving the changes in the file, clear your project application with php symfony cache:clear and when there's an unhandled exception in your app, an email will be sent to notify you about the exception (with description).
Happy coding !