什么时候最好在PHP中使用异常?
我通常通过返回什么时候最好在PHP中使用异常?,php,exception,error-handling,Php,Exception,Error Handling,我通常通过返回false来指示方法中的错误,但它在语义上并不总是与我一致(取决于方法,false可能是有效的返回) 我已经研究过例外情况,我想知道它们是否是一个一刀切的解决方案?我是否应该返回false我仍然可以返回的位置 我可能完全没有抓住要点,所以请耐心听我说 // My old way function getProductById($id) { if ( ! is_numeric($id)) { return false; } } //
false
来指示方法中的错误,但它在语义上并不总是与我一致(取决于方法,false
可能是有效的返回)
我已经研究过例外情况,我想知道它们是否是一个一刀切的解决方案?我是否应该返回false
我仍然可以返回的位置
我可能完全没有抓住要点,所以请耐心听我说
// My old way
function getProductById($id) {
if ( ! is_numeric($id)) {
return false;
}
}
// My consideration
function getProductById($id) {
if ( ! is_numeric($id)) {
throw new Exception('The id must be numerical!');
}
}
例外情况很好!允许您使错误处理代码远离错误代码 返回
false
可能是函数的有效答案,这是正确的。如果你抛出一个错误,你也可以抓住它并做一些更有用的事情
当我说它有助于使错误处理代码远离您的错误时,请考虑此
try {
func1($a);
func2($b);
func3($c);
} catch (Exception $e) {
// error handling here
}
因此,您不需要检查每个函数的错误返回并对其进行操作。
< P>我只建议使用一种样式,因此,如果您已经通过错误返回到您的应用程序,那么您应该考虑保持它。 但是,如果您想为异常重写代码,请注意异常在PHP中是非常需要资源的(CPU时间和内存)。我想通过示例演示:假设有一个函数Product::getById($id)
。如果希望此函数在找不到id时引发异常,则一切正常。但是,如果您想在单个页面请求中多次调用该函数并收集所有不存在的ID,您可能首先考虑在循环中捕获异常。这导致了经济的大幅放缓。这些选择包括:
- 复制代码(创建一个名为
的函数)Product::getByIdWithoutException()
- 为此用例创建一个专用函数(
)。这是最好的解决方案,但并不总是可行的(如果不重写大量代码或拥有大量参数列表,或与软件工程的其他最佳实践相违背,等等)Product::getAllIds(array$ids)
function getById($id, $throwException = true) {
if (!self::idExists($id)) {
if ($throwException) {
throw new IdNotFoundException();
} else {
return NULL;
}
}
return self::getByWhereClause('id = ' . self::escape($id), $throwException);
}
我想你会发现这很有用。据乔尔·斯波尔斯基说 关于异常处理,我的一般经验法则是首先尝试为最终用户维护应用程序流,这可以通过从一开始就不在PHP中抛出异常来实现,但有时它们是有用的 我倾向于根据可能导致触发问题的状态的条件来判断是抛出异常还是返回布尔值false或其他处理方法 执行特定代码块时,这是正常的、合理的值还是状态?如果是这样,那么您可能只想返回一个布尔值false或其他一些值,指示代码块达到故障点 如果您担心可能存在非正常值或状态,或者该值或状态是由于某人忘记正确初始化代码中的变量而导致的,那么异常可能是合适的,因为这将为您作为开发人员提供即时反馈。这里的两个示例是必须在对象构造函数中设置的必需属性,但是没有正确指定值,或者如果您有一个不应该对对象调用方法的场景,那么如果调用该对象,您可能希望引发异常 简而言之,我倾向于使用最合适的工具。如果我处理的是正常应用程序执行的一部分,那么我通常会返回一个值来指示失败。如果发生了无效的情况,那么我抛出一个异常,以便处理该问题
我想你可以说,我使用异常只是为了捕捉那些应该真正停止最终用户应用程序执行的事情,但我的编码思想是,通过适当的测试,这些代码行都不应该在野外执行。我的思路是: 如果一段代码由于前置条件失败而无法工作,则抛出异常。 因此,如果您的
getProductById()
方法没有提供正确类型的值来执行它应该执行的操作,这就是引发异常的原因
这使您能够更快地发现问题,因为“无结果”和“潜在无效状态”之间有明确的区别。如果您习惯于在这种情况下抛出异常,它会让您安心,因为它将很难失败,而不是以未定义/意外的方式继续
我会返回false
或null
,如果一切都按预期(定义)运行,但过程就是找不到匹配的产品
注:这也是为什么根据我的定义,从输入验证中抛出异常是错误的。代码的全部目的是验证输入,因此可以预期无效输入,因此不会出现异常。这是一个有趣的想法。。。我还不知道我是否想把我的参数列表弄得乱七八糟。我曾经回答过一个类似的问题,那里的答案可能也很有用:这是真的,我大体上同意,但你应该提到可能的性能缺点(异常的成本)!