为什么以及如何在此示例 PHP 代码中使用异常?

我一直在想为什么我会在我的PHP中使用异常。让我们看一个简单的例子:

class Worker
{
 public function goToWork()
 {
  return $isInThatMood ?
  // Okay, I'll do it.
  true : 
  // In your dreams...
  false;
 }
}

$worker = new Worker;
if (!$worker->goToWork())
{
 if (date('l',time()) == 'Sunday')
  echo "Fine, you don't have to work on Sundays...";
 else
  echo "Get your a** back to work!";
}
else
 echo "Good.";

我有理由对这种代码使用异常吗?为什么?如何构建代码?

那么可能产生错误的代码呢:

class FileOutputter
{
 public function outputFile($file)
 {
  if (!file_exists($file))
   return false;
  return file_get_contents($file);
 }
}

在上述情况下,我为什么要使用例外?我有一种感觉,异常可以帮助您识别问题的类型,这是真的吗?

那么,我是否在此代码中适当地使用了异常:

class FileOutputter
{
 public function outputFile($file)
 {
  if (!file_exists($file))
   return throw new Exception("File not found.",123);
  try
  {
   $contents = file_get_contents($file);
  }
  catch (Exception $e)
  {
   return $e;
  }
  return $contents;
 }
}

还是那么穷?现在,底层代码可以执行此操作:

$fo = new FileOutputter;
try
{
 $fo->outputFile("File.extension");
}
catch (Exception $e)
{
 // Something happened, we could either display the error/problem directly
 echo $e->getMessage();
 // Or use the info to make alternative execution flows
 if ($e->getCode() == 123) // The one we specified earlier
  // Do something else now, create "an exception"
}

还是我在这里完全迷失了?


答案 1

何时应使用异常?

您使用异常来指示异常条件;也就是说,阻止方法履行其契约的东西,并且不应该在该级别发生。

例如,您可能有一个方法 ,它将对记录的更改保存到数据库中。如果由于某种原因无法做到这一点(例如,发生数据库错误或数据约束被破坏),那么您可以抛出一个异常来指示失败。Record::save()

如何创建自定义例外?

异常通常被命名为指示错误的性质,例如,。您可以以这种方式创建自定义命名的例外的子类,例如DatabaseExceptionException

class DatabaseException extends Exception {}

(当然,您可以利用继承来为此异常提供一些其他诊断信息,例如连接详细信息或数据库错误代码。

何时不应使用异常?

再举一个例子;检查文件是否存在的方法。如果文件不存在,这可能不应该引发异常,因为该方法的目的是执行所述检查。但是,打开文件并执行某些处理的方法可能会引发异常,因为该文件应存在,依此类推。

最初,并不总是清楚某些事情何时是例外,何时不是例外。像大多数事情一样,随着时间的推移,经验会教你什么时候应该和不应该抛出异常。

为什么使用异常而不是返回特殊的错误代码等?

关于异常的有用之处在于,它们会立即跳出当前方法并引导调用堆栈,直到它们被捕获和处理,这意味着您可以将错误处理逻辑向上移动,尽管理想情况下不会太高。

通过使用明确的机制来处理故障情况,您可以在发生错误情况时自动启动错误处理代码,这意味着您可以避免处理必须检查的各种神奇的哨兵值,或者更糟糕的是,全局错误标志来区分一堆不同的可能性。


答案 2

我不是PHP程序员,但这看起来类似于C#。

通常,如果它是一个不归路点,你会想要抛出错误。然后,您将能够记录一些东西来表明不可能的事情发生了。

如果你能分辨出该文件不存在,那么你就可以这么说。在我看来,没有必要也抛出一个异常。

现在,如果文件被发现并且您正在处理它,并且说只有一半的文件已上传,并且您无法无一例外地告诉它,那么最好有一些。

我想说的是,避免捕获所有异常“捕获(异常$e)”并通过合同进行设计是一种很好的设计实践,就像您在前面的示例中所做的那样。首先,我会更具体地说明引发的异常类型,然后根据需要从那里开始工作。否则,请远离尝试>捕获和异常。


推荐