PHP致命错误:未捕获的异常'Exception'

11

我正在尝试使用PHP中的异常处理。例如,我有一个脚本,它读取一个 $_GET 请求并加载一个文件;如果文件不存在,则应该抛出新的异常:

if ( file_exists( $_SERVER['DOCUMENT_ROOT'] .'/'.$_GET['image'] ) ) {
    // Something real amazing happens here.
}
else {
    throw new Exception("The requested file does not exists.");
}

问题在于,当我尝试为测试提供一个不存在的文件时,我得到了一个500错误而不是异常信息。服务器日志如下:

[09-Jul-2013 18:26:16 UTC] PHP Fatal error:  Uncaught exception 'Exception' with message 'The requested file does not exists.' in C:\sites\wonderfulproject\script.php:40
Stack trace:
#0 {main}
  thrown in C:\sites\wonderfulproject\script.php on line 40

我想知道是否有什么非常明显的东西我没注意到。

我已经查看了这个问题:PHP致命错误:未捕获异常'Exception',信息为,但它与我的问题不完全相同,并且没有简洁的答案。

请帮忙吗?

*编辑*

看起来这与throw关键字有关。例如,如果我使用echo,我会在屏幕上打印出消息,就像这样:

exception 'Exception' with message 'The file does not exists.' in C:\sites\wonderfulproject\script.php:183 Stack trace: #0 {main}

这是为什么呢?

**编辑2**

感谢@Orangepill,我更好地理解了如何处理异常。我发现一个非常好的教程来自nettuts,对我很有帮助。链接:http://net.tutsplus.com/tutorials/php/the-ins-and-outs-of-php-exceptions/


3
你的日志记录了你想要记录的内容,问题出在哪里? - Dany Caissy
1
file_exists 显然返回了 false,很可能是因为该文件实际上不存在 - deceze
问题在于我得到了一个500 - 内部服务器错误,而不是在屏幕上显示我的消息和堆栈跟踪的异常。 - darksoulsong
1
请注意路径遍历攻击! - Zwirbelbart
3个回答

22
这是未捕获异常的预期行为,因为display_errors被关闭。
您的选择是通过php或ini文件打开display_errors,或者捕获并输出异常。
 ini_set("display_errors", 1);

或者

 try{
     // code that may throw an exception
 } catch(Exception $e){
     echo $e->getMessage();
 }

如果你抛出异常,意图是希望在后续的代码中有地方能够捕获并处理它。如果没有的话,那就是一个服务器错误(500)。
另一个选择是使用set_exception_handler来为你的脚本设置一个默认的错误处理程序。
 function default_exception_handler(Exception $e){
          // show something to the user letting them know we fell down
          echo "<h2>Something Bad Happened</h2>";
          echo "<p>We fill find the person responsible and have them shot</p>";
          // do some logging for the exception and call the kill_programmer function.
 }
 set_exception_handler("default_exception_handler");

不错。但是我认为我可以在try catch块之外抛出异常,如果我错了,请纠正我。 我已经更新了我的问题,并描述了我尝试过的内容。 - darksoulsong
你可以这样做,但是你会得到一个500服务器错误信息 :).... 抛出异常除了给自己捕获和处理它的机会外,没有任何意义,或者至少为最终用户格式化一个信息丰富的“糟糕”页面,如果异常无法恢复。 - Orangepill
try/catch 不一定要在抛出异常的函数中,它也可以在执行堆栈中更深层次的位置,比如在调用该函数的调用方或该函数的调用方。 - Orangepill
@darksoulsong 更新了答案,展示了使用 set_exception_handler 创建 Pokemon 异常处理程序( gotta catch'em all ),以处理那些悄悄溜过 try/catch 块的异常。 - Orangepill

10

在此添加一些额外的信息,以防有人遇到和我一样的问题。

我的代码中使用了命名空间,并且我有一个函数会抛出异常。

然而,在另一个类文件中,我的try/catch代码完全被忽略了,并且会抛出未捕获异常的常规PHP错误。

结果是我忘记在顶部添加"use \Exception;",添加后问题得到解决。


1
或者您可以在调用类时定义路径: throw new \Exception(...);请注意,前导“\”用于定义根目录中的类路径。 - DeeZone
1
谢谢 @xorinzor 解决我的问题!我快要疯了... - Joe

0

对于

throw new Exception('test exception');

我得到了500(但在浏览器中没有看到任何内容),直到我放置了

php_flag display_errors on

在我的 .htaccess 文件中(仅针对子文件夹)。 还有更详细的设置, 请参见 仅通过 htaccess 启用 php 错误显示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接