* ver o primeiro comentário para ajustar um bug de loop eterno na homepageObjetivo: Logar qualquer exceção não tratada no código, mandar um email para a equipe, gravar um log e mostrar uma mensagem para o usuário do tipo: "Estamos em manutenção para melhor servir." enquanto a equipe corre pra consertar o erro.
Como Fazer1 Primeiro conectamos um listener ao evento de exception. Inicialmente pensei em capturar isso com um filtro, mas vi que existem algumas exceções que são capturadas que atrapalham o bom funcionamento do framework, como por exemplo a ReflectionException que vai gerar um 404 mais na frente.
Usando um listener para o evento, capturamos apenas aquilo que o symfony não trata:
class frontendConfiguration extends sfApplicationConfiguration {
public function configure() {
$this->dispatcher->connect(
'application.throw_exception',
array('MyExceptionHandler', 'listenToApplicationException')
);
}
...
2 Depois criamos a classe que ser chamada, contendo o método que vai "ouvir" o evento, conforme determinamos acima:
class MyExceptionHandler extends sfFilter {
static public function listenToApplicationException($event)
{
// pegamos a exception original
$e = $event->getSubject();
// para passar um link na mensagem mostrada ao usuário
sfLoader::loadHelpers(array('Url'));
try {
// manda email e grava um log
self::notify($e);
}
catch(Exception $e) {
// "Engulindo" propositadamente os
// erros quando envia email de log
// para não impedir que a mensagem
// seja mostrada para o usuário
}
if(self::isAjax()) {
// lembre dos requests de ajax...
// tratar de acordo com o framework do freguês.
}
else {
sfContext::getInstance()->getUser()->setFlash(
'feedback',
sprintf(
Messages::UNEXPECTED_ERROR,
url_for('@support')
)
);
sfContext::getInstance()->getController()->redirect('@homepage');
}
// este evento específico chama cada listener até que um responda que pôde tratar o evento. Por isso esse retorno.
return true;
}
static function notify(Exception $e) {
// cria a mensagem...manda email e registra um log.
self::log($mensagem);
}
static function log($message) {
$exceptionLogLocation = sfConfig::get('sf_log_dir') . '/exceptions.log';
$fileHandle = fopen($exceptionLogLocation, "a+");
fwrite($fileHandle, $message."\n");
}
static function isAjax(){
return sfContext::getInstance()->getRequest()->isXmlHttpRequest() ||
sfContext::getInstance()->getRequest()->hasParameter('iframeAjaxUpload');
}
}
3 Feito. Fica aqui mais uma dica de algumas coisas que você pode capturar e colocar na mensagem para facilitar a vida depois:
$username = sfContext::getInstance()->getUser()->getService()->getUsername();
$referer = sfContext::getInstance()->getRequest()->getReferer();
$uri = sfContext::getInstance()->getRequest()->getUri();
$ajax = self::isAjax() ? 'Yes' : 'No';
'time' => date('Y-m-d H:i:s'),
'exception_class' => get_class($e),
'exception_message' => $e->getMessage(),
'trace' => $e->__toString()