我正在构建一个相对较小但关键任务的应用程序,它将同步两个数据库。这个应用程序将在部署后每晚运行一次计划任务,很可能是无人监管的。
我遇到的问题是我尝试实现的异常处理机制没有显示很多错误。错误不会被抛出或被捕获,我不知道并且调试是非常劳动的,因为很多错误(大多数)没有按预期显示到控制台。
基本上我正在努力的是让它在编码时向控制台发送错误,在生产模式下发送日志和电子邮件。我在脚本开头设置了一个常量:
define("APPMODE", "DEBUG");
我已经设置了一个自定义错误处理程序:
/*
* Gestionnaire d'erreur qui trappe les erreures et warnings.
* et les renvois sous formes d'exceptions.
*/
function CustomErrorHandler($errno, $errstr, $errfile, $errline) {
if ( $errno >= 2 ) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
// return true;
}
return false;
}
此错误处理程序和其他错误设置在静态类函数中初始化,如下所示:
/**
* Configuration de la gestion d'erreurs
*/
static function initErrorHandling($config){
/*
* Lance des exceptions avec toutes les erreures
* Permet de rediriger vers fichiers logs ou courriels.
*/
set_error_handler('CustomErrorHandler');
// Adapts error handling according to APPMODE
error_reporting($config->error_level);
ini_set('display_startup_errors', $config->display_errors);
}
现在,有了这个,我虽然我需要做的就是定义适当的异常处理机制,即在扩展异常类中实现必要时记录和发送电子邮件的逻辑。这是我的主要异常类:
<?php
class InitException extends Exception{
protected $previous;
// Redefine the exception so message isn't optional
public function __construct($message, $code = 0, Exception $previous = null) {
$this->previous = $previous;
// make sure everything is assigned properly
parent::__construct($message, $code, $previous);
}
// Send message to logfile or console depending on APPMODE
public function __toString() {
$logfile = 'C:\tirelinkCRMsynch\logs\customerAccountsSync.log';
switch(APPMODE){
/*
* This mode writes errors to logfile and sends a notice by email.
*/
case 'PROD':
$message = "\r\n" . date(DATE_ATOM) . " ". __CLASS__ . ": [{$this->code}]: {$this->getMessage()} \r\n\t\t\t\t\t\t in {$this->getFile()} , line {$this->getLine()}\r\n";
$message .= "Previous = {$this->previous}";
// Mail the error
mail_error($message);
// Log error
if (is_writable($logfile)){
if (!$handle = fopen($logfile, 'a')) {
echo "Cannot open file ($logfile)";
exit;
}
// Write $message to our opened file.
if (fwrite($handle, $message) === FALSE) {
echo "Cannot write to file ($logfile)";
exit;
}
fclose($handle);
}else{
echo "Cannot write to ($logfile)";
exit;
}
return "Caught Exception of type [" . __CLASS__ . "] -> check logfile for more info.\r\n";
break;
/*
* DEBUG mode writes errors to console
*/
case 'DEBUG': //
return "Caught exception of type " . __CLASS__ . ": [{$this->code}]: {$this->message} in {$this->getFile()} on line {$this->getLine()}.\r\nPrevious = {$this->previous}";
break;
}
}
public function mailError($msg) {
// to do - setup zend_mailer
$mail = '';
echo "Mailed";
}
现在。最后但并非最不重要的,“捕获块”。我真的不确定我是否在本节中以正确的方式做事。我的想法是,由于脚本在执行时代表一个工作单元,整个脚本被包装在try-catch块中,在脚本最终退出后放置了catch块:
<code for processing above>
exit();
} catch (Zend_Config_Exception $e){
throw new InitException($e->getMessage(), 100, $e);
} catch (Zend_Mail_Transport_Exception $e){
throw new InitException($e->getMessage(), 200, $e);
} catch (Zend_Mail_Exception $e){
throw new InitException($e->getMessage(), 300, $e);
} catch (Zend_Exception $e){
throw new InitException($e->getMessage(), 400, $e);
} catch (ErrorException $e){
throw new InitException($e->getMessage(), 500, $e);
} catch (DBException $e){
throw new InitException($e->getMessage(), 600, $e);
} catch (InitException $e){ // Cette clause attrape toutes les erreures / warnings du script.
$e->__ToString();
} catch (Exception $e){
echo $e->__toString();
die ("Caught generic exception in {$e->getFile()} on line {$e->getLine()}");
}
?>