这更像是一个架构问题。我想知道人们对如何在完全面向对象的PHP环境中正确处理错误的看法。
例如,我有一个从数据库中检索所有用户数据的类。所以我会以这种方式使用它:
$userData = new UserDataConnection();
$userData->openDatabase();
$userData->retrieveData();
$userData->showData();
$userData->closeDatabase();
在每个步骤中,都可能发生错误。那么我会从每个步骤返回一个布尔值来说明函数是否已成功执行(因此错误检查在每个函数中),或者我是否围绕整个事件执行try-catch异常处理?还是有更好的方法?
当出现某种错误时,总是去某种错误页面也会更好吗?
答案 0 :(得分:1)
<?php
$ERROR = false;
try {
$userData = new UserDataConnection();
$userData->openDatabase();
$userData->retrieveData();
$DETAILS = $userData->showData();
$userData->closeDatabase();
} catch( Exception $e ) {
$ERROR = $e->getMessage(); // exit;
}
if( $ERROR ) {
$DETAILS = array();
}
?>
如果您使用PDO,则可以抛出PDOException。
答案 1 :(得分:1)
它通常归结为一个简单的问题:
这个功能可能“合法地”失败,或者是否有任何失败的迹象表明出现了什么问题?
如果函数需要某种输入,并且永远不应该使用不同类型的输入调用,则任何提供正确输入的失败都是InvalidArgumentException
。对于不直接处理用户输入的函数尤其如此。这种类型提示效果更好。
如果函数在给定正确输入的情况下应始终产生某个结果,则函数产生该结果的任何失败都是RuntimeException
或LogicException
或其他类型的异常。
如果函数可能产生或不产生某种结果,false
是合法的返回值。返回false
时,处理用户输入并因此得到非常随意的输入值的函数通常很好。
一些例子:
getDatabaseConnection()
完全正确抛出RuntimeException
或类似内容。这是特殊情况,在这种情况下,无法继续工作。transformFooIntoBar(Foo $foo)
如果由于某种原因无法返回Bar
实例,则抛出某种形式的异常是正确的。该功能具有明确的目的和类型检查输入值。如果它不能在如此明确的条件下完成工作,那么事情显然是错误的,必须加以解决。 Ergo,一个例外。checkIfUserExists($id)
可能会返回false
,因为它的工作是竖起大拇指或竖起大拇指。在此作业说明的情况下,不存在的用户不是例外情况。捕获抛出异常的位置取决于您要处理它的位置。数据库连接错误应该可以在调用堆栈的最顶层捕获,因为如果数据库关闭,您可能无法执行任何操作。
另一方面,如果某个模块正在调用某个子模块,而另一半模块预计该子模块失败和/或有一个应急计划,以防它失败,模块可能会捕获子模块的异常并继续完成其工作。例如,getRSSUpdates()
会调用HTTP::fetchContents($url)
。如果URL返回404,则HTTP
模块可能会抛出异常,因为在这些情况下它不能返回内容。尽管getRSSUpdates()
函数已准备就绪,但将此情况称为“此时没有更新”。