我看到很多教程演示了简单的try catch,例如打开文件。但我从未见过一个真正的大型实例。有人能给我提供一些他们已经或将要使用异常的情况吗?而且为了抛出异常,是否真的需要扩展异常类?最后,当抛出异常时,它会导致脚本 exit(); 吗?还是记录并继续执行脚本?
我看到很多教程演示了简单的try catch,例如打开文件。但我从未见过一个真正的大型实例。有人能给我提供一些他们已经或将要使用异常的情况吗?而且为了抛出异常,是否真的需要扩展异常类?最后,当抛出异常时,它会导致脚本 exit(); 吗?还是记录并继续执行脚本?
class RegistrationFailed extends Exception {}
现在,在我们的注册代码中的catch
语句中,我们可以测试RegistrationFailed异常并相应地处理它。否则,当异常不是RegistrationFailed时,我们允许其冒泡,因为我们对其不感兴趣。
try {
// do registration here
}
catch(RegistrationFailed $e) {
// handle the failed registration
}
catch(SomeOtherException $e) {
// handle other errors like this...
}
// All other errors will not be caught and will bubble up
catch(Exception $e)
,因为这样你就可以处理之前没有处理过的其他异常。 - Sk8erPeter异常通常用于处理错误(至少在PHP中是这样)。假设您正在执行某个例程,发生了一个错误,而您无法在当前上下文中处理该错误。
例如:
<?php
/**
* @throws Exception_NoFile
*/
function read_file($file) {
if(!file_exists($file)) {
throw new Exception_NoFile($file);
}
/* ... nominal case */
}
返回一个无效的返回值(这是C语言的惯例,例如:返回-1或使用状态标志)
抛出异常,并希望有人能在上面捕获它。如果您的客户端代码期望它,那么没问题,它可以尝试另一条路径或重新抛出异常。如果您的客户端没有准备好处理请求的文件不存在的情况...您的代码将因为未捕获的异常而失败,就像在其他方法中读取不存在的文件时一样。
按照您的日志框架指南记录异常及其消息和堆栈跟踪,以便正确记录。您不希望失去任何一个。
我觉得很多人把“失败”和“异常”混为一谈。“错误”这个词可以同时指二者,但我使用它来表示“失败”。
失败 - 当操作未成功时
异常 - 当出现意外或超出正常流程条件时
例如,如果一个机器人试图走到目的地却没有成功,那就是失败。但如果它断了腿或屋顶掉下来了,那就是异常。
如果屋顶掉下来了,我会抛出一个异常,说明屋顶掉下来了。
如果机器人没有到达目的地,我不会抛出异常,而是返回false或返回一个错误信息,比如“无法到达目的地,因为屋顶掉下来了。”
try {
Walk to the cabinet;
}
catch (RoofFell_Exception $e) {
return "Could not reach the destination because the roof fell.";
}
catch (Legbroke_Exception $e) {
return "Could not reach the destination because a leg broke.";
}
if($current_location == 'cabinet') {
return "Destination reached";
}
return false;
在程序尝试连接或访问I/O(文件、数据库、网络、设备)时,使用异常处理是一个很好的选择。
当调用代码块(函数/方法)尝试访问文件时,请使用异常处理。
当调用代码块(函数/方法)尝试建立数据库连接时,请使用异常处理。
当调用代码块(函数/方法)尝试在数据库上运行查询时(任何尝试访问数据库表/视图等),请使用异常处理。
对于网络连接或访问也可以这样说。
内存访问需要I/O(包括将东西存储在$_SESSION文件中),但大多数初学者不会将整个程序放在try...catch
结构的限制范围内。关于异常的使用和扩展Exception类的很好的例子可以在Matt Doyle的书《Beginning PHP 5.3》第20章652-60页中找到。
set_error_handler()
、trigger_error()
、error_log()
的使用结合在catch
块内,可以让您保留在开发中向输出设备(浏览器/stdout)回显的自定义、开发人员友好的错误消息。也就是说,在生产环境中,您的php.ini将关闭display_errors
并打开log_errors
。当连接到会计数据库失败时,您可能已经回显了类似于“糟糕,我无法连接到会计数据库”的内容,现在只需将相同的文本字符串发送到error_log()
,您的个人错误消息仍然可以被记录。
示例:
function custom_handler($arg1, $arg2, $arg3, $arg4, $arg5)
{
...
...
error_log(blah, blah, blah)
}
set_error_handler('custom_handler'); <--takes over this duty from PHP
$error = NULL;
try
{
if(!connect_to_mythical_database('accounting'))
{
$error = 'I cannot connect to the accounting database';
throw new Exception(supply-correct-arguments);
}
}
catch (Exception $e)
{
trigger_error(supply-correct-arguments); <-- does what 'custom_handler' instructs.
error_log($error, blah, blah); <---Your friendly message here
header('Location: http://www.myhomepage.com');
exit;
}
注意:在custom_handler()
内部,您可以使用error_log()
将PHP错误消息记录在文件中、通过电子邮件发送或同时记录和发送标准的PHP错误消息。因此,trigger_error()
要么由PHP(默认)控制,要么由您的“custom_handler”控制,后者可以实现error_log()
,所有这些都可以通过异常处理程序的catch
块激活。
异常仅仅是将边缘情况或错误(实际上只是大型边缘事件)从代码的主体中移出,以防它们使得99%的基本流程代码充斥着大量的开关/条件语句。
你可以将其看作一种反转的switch语句,其中try{}内部的事件确定发生哪个(如果有任何)catch块。
这意味着如果您不喜欢它们,则无需使用它们。但它们可以使代码更易于阅读。