2011-01-23 53 views
2

基本上我有一个自定义异常处理程序。当我处理一个异常时,我只想让它回应消息并继续执行脚本。但在我的方法处理异常后,脚本不会继续。PHP异常处理程序杀死脚本

这是PHP的行为还是我的异常处理程序做错了什么?

+2

请参阅本手册中的此评论:http://www.php.net/manual/en/function.set-exception-handler.php#95170 – 2011-01-23 21:55:17

回答

3

这是php的行为。这与set_error_handler()的不同之处在于,根据set_exception_handler(),的手册,调用exception_handler后执行将停止。因此,请确保您捕获所有例外情况,只允许您通过要求杀死您的脚本。

其实,这也就是为什么set_error_handler()不将所有错误异常时异常和set_exception_handler()搭配都非常好......除非你实际上意味着你的应用程序中,从而严格编码的任何通知或警告停止脚本。但至少它会给你一个涉及未设置数组键的调用的跟踪。

2

随着custom exception handler,你会想要在try/catch块中捕捉异常,并在那里做任何你想要的处理。

以下是如果你想赶上并打印任何未处理的异常从The CodeUnit of Craig

try { 
    $error = 'Throw this error'; 
    throw new Exception($error); 
    echo 'Never get here'; 
} 
catch (Exception $e) 
{ 
    echo 'Exception caught: ', $e->getMessage(), "\n"; 
} 

的例子,你可以设置一个顶层异常处理像this example from w3schools(near the bottom of the page)

<?php 
function myException($exception){ 
    echo "<b>Exception:</b> " , $exception->getMessage(); 
} 

set_exception_handler('myException'); 

throw new Exception('Uncaught Exception occurred'); 
?> 

应打印“异常:发生未捕获的异常“

+1

你不理解我的问题,当我在我的未处理的exeption中处理程序,我想脚本显示一个错误mesasge,然后继续与脚本 – Ozzy 2011-01-23 22:03:15

+0

修改我的答案显示一些示例代码,将打印任何其他未处理的异常。 – Bryan 2011-01-23 22:15:59

0

请看下面的代码。它的工作对我来说:

define(BR, "<br/>"); 
try { 
    echo "throwing exception" . BR; 
    throw new Exception("This is exception"); 
} 
catch(Exception $ex) { 
    echo "caught exception: " . BR . $ex->getMessage() . BR; 

} 
echo "Keep on going!. ..." . BR; 

它打印如下:

throwing exception 
caught exception: 
This is exception 
Keep on going!. ... 

你说什么? 你可以显示你的代码处理程序的代码吗?

+1

我相信OP意味着使用`set_exception_handler()`函数创建一个通用的catch来完全替换某些try/catch块,同时继续处理脚本的效果......这是不可能的。 – 2011-01-24 01:27:03

0

你可以这样做:

function handleError($errno, $errstring, $errfile, $errline, $errcontext) { 
    if (error_reporting() & $errno) { 
     // only process when included in error_reporting 
     return processError($errno, $errstring); 
    } 
    return true; 
} 

function handleException($exception){ 
    // Here, you do whatever you want with the generated 
    // exceptions. You can store them in a file or database, 
    // output them in a debug section of your page or do 
    // pretty much anything else with it, as if it's a 
    // normal variable 
} 

function processError($code, $message){ 
    switch ($code) { 
     case E_ERROR: 
     case E_CORE_ERROR: 
     case E_USER_ERROR: 
      // Throw exception and stop execution of script 
      throw new Exception($message, $code); 
     default: 
      // Execute exception handler and continue execution afterwards 
      return handleException(new Exception($message, $code)); 
    } 
} 

// Set error handler to your custom handler 
set_error_handler('handleError'); 
// Set exception handler to your custom handler 
set_exception_handler('handleException'); 


// ---------------------------------- // 

// Generate warning 
processError(E_USER_WARNING, 'This went wrong, but we can continue'); 

// Generate fatal error : 
processError(E_USER_ERROR, 'This went horrible wrong'); 

另一种方法:

function handleError($errno, $errstring, $errfile, $errline, $errcontext) { 
    if (error_reporting() & $errno) { 
     // only process when included in error_reporting 
     return handleException(new \Exception($errstring, $errno)); 
    } 
    return true; 
} 

function handleException($exception){ 
    // Here, you do whatever you want with the generated 
    // exceptions. You can store them in a file or database, 
    // output them in a debug section of your page or do 
    // pretty much anything else with it, as if it's a 
    // normal variable 

    switch ($code) { 
     case E_ERROR: 
     case E_CORE_ERROR: 
     case E_USER_ERROR: 
      // Make sure script exits here 
      exit(1); 
     default: 
      // Let script continue 
      return true; 
    } 
} 

// Set error handler to your custom handler 
set_error_handler('handleError'); 
// Set exception handler to your custom handler 
set_exception_handler('handleException'); 


// ---------------------------------- // 

// Generate warning 
trigger_error('This went wrong, but we can continue', E_USER_WARNING); 

// Generate fatal error : 
trigger_error('This went horrible wrong', E_USER_ERROR); 

后一种策略的优点是,你得到的$errcontext参数,如果你的功能handleException内做$exception->getTrace()

这对于某些调试目的非常有用。不幸的是,这仅适用于直接从您的上下文中使用trigger_error的情况,这意味着您不能使用包装函数/方法来为trigger_error函数设置别名(所以如果您希望跟踪中的上下文数据不能执行类似function debug($code, $message) { return trigger_error($message, $code); }的操作)。


编辑

我找到了一个解决办法dirtytrigger_error问题。

考虑下面的代码:

define("__DEBUG__", "Use of undefined constant DEBUG - assumed 'DEBUG'"); 

public static function handleError($code, $message, $file, $line, $context = false) { 
    if ($message == __DEBUG__) { 
     return static::exception(new \Exception(__DEBUG__, E_USER_WARNING)); 
    } else { 
     if (error_reporting() & $code) { 
      return static::exception(new \Exception($message, $code)); 
     } 
     return true; 
    } 
} 

public static function handleException($e) { 
    global $debug; 
    $code = $e->getCode(); 
    $trace = $e->getTrace(); 
    if ($e->getMessage() == __DEBUG__) { 
     // DEBUG 
     array_push($debug, array(
      '__TIME__' => microtime(), 
      '__CONTEXT__' => array(
       'file' => $trace[0]['file'], 
       'line' => $trace[0]['line'], 
       'function' => $trace[1]['function'], 
       'class' => $trace[1]['class'], 
       'type' => $trace[1]['type'], 
       'args' => $trace[0]['args'][4] 
      ) 
     )); 
    } else { 
     // NORMAL ERROR HANDLING 
    } 
    return true; 
} 

有了这个代码,你可以使用语句DEBUG;产生的所有可用变量列表和任何特定的上下文堆栈跟踪。该列表存储在全局变量$debug中。您可以将其添加到日志文件,将其添加到数据库或打印出来。

虽然这是一个非常非常肮脏的黑客,因此可以自行决定使用它。但是,它可以使调试更容易,并允许您为调试代码创建一个干净的UI。