PHP中的错误处理

时间:2008-09-25 16:21:06

标签: php error-handling

我熟悉一些基础知识,但我想知道更多关于何时以及为什么错误处理(包括抛出异常)应该在PHP中使用,尤其是在实时网站或Web应用程序上。是否可以过度使用,如果是这样,过度使用会是什么样的?是否有不应该使用的情况?此外,有关错误处理的一些常见安全问题是什么?

9 个答案:

答案 0 :(得分:31)

添加到已经说过的内容的一件事是,将Web应用程序中的任何错误记录到日志中是至关重要的。这样,正如Jeff“Coding Horror”Atwood建议的那样,你会知道你的用户何时遇到应用程序问题(而不是“问他们有什么不对劲”)。

为此,我建议使用以下类型的基础架构:

  • 在数据库中创建一个“crash”表和一组用于报告错误的包装类。我建议为崩溃设置类别(“阻止”,“安全”,“PHP错误/警告”(与例外)等)。
  • 在所有错误处理代码中,请务必记录错误。一直这样做取决于你构建API的程度(上面的步骤) - 如果做得对,它应该琐碎来记录崩溃。

额外信用:有时,您的崩溃将是数据库级崩溃:即数据库服务器崩溃等。如果是这种情况,您的错误记录基础结构(上面)将失败(您无法将崩溃记录到数据库,因为日志尝试写入DB)。在这种情况下,我会将您的Crash包装器类中的故障转移逻辑写入

  • 向管理员发送电子邮件,和/或
  • 将崩溃的详细信息记录到纯文本文件

所有这些听起来都有点矫枉过正,但请相信我,这对您的应用程序是否被接受为“稳定”或“片状”有所不同。这种差异来自这样一个事实,即所有应用程序始终都是片状/崩溃,但那些了解其应用程序所有问题的开发人员有机会实际修复它。

答案 1 :(得分:24)

粗略地说,错误是PHP的遗产,而异常是处理错误的现代方法。最简单的方法是设置一个抛出异常的错误处理程序。这样,所有错误都转换为异常,然后您可以简单地处理一个错误处理方案。以下代码会将错误转换为异常:

function exceptions_error_handler($severity, $message, $filename, $lineno) {
  if (error_reporting() == 0) {
    return;
  }
  if (error_reporting() & $severity) {
    throw new ErrorException($message, 0, $severity, $filename, $lineno);
  }
}
set_error_handler('exceptions_error_handler');
error_reporting(E_ALL ^ E_STRICT);

但有一些情况,其中代码专门用于处理错误。例如,schemaValidate method of DomDocument在验证文档时会发出警告。如果将错误转换为异常,它将在第一次失败后停止验证。有时这是你想要的,但是在验证文档时,你可能实际上想要所有失败。在这种情况下,您可以临时安装收集错误的错误处理程序。这是一个小片段,我用于此目的:

class errorhandler_LoggingCaller {
  protected $errors = array();
  function call($callback, $arguments = array()) {
    set_error_handler(array($this, "onError"));
    $orig_error_reporting = error_reporting(E_ALL);
    try {
      $result = call_user_func_array($callback, $arguments);
    } catch (Exception $ex) {
      restore_error_handler();
      error_reporting($orig_error_reporting);
      throw $ex;
    }
    restore_error_handler();
    error_reporting($orig_error_reporting);
    return $result;
  }
  function onError($severity, $message, $file = null, $line = null) {
    $this->errors[] = $message;
  }
  function getErrors() {
    return $this->errors;
  }
  function hasErrors() {
    return count($this->errors) > 0;
  }
}

用例:

$doc = new DomDocument();
$doc->load($xml_filename);
$validation = new errorhandler_LoggingCaller();
$validation->call(
  array($doc, 'schemaValidate'),
  array($xsd_filename));
if ($validation->hasErrors()) {
  var_dump($validation->getErrors());
}

答案 2 :(得分:2)

无法处理的错误会停止脚本,仅此一点就是处理它们的理由。

通常,您可以使用Try-Catch块来处理错误

try
{
    // Code that may error
}
catch (Exception $e)
{
    // Do other stuff if there's an error
}

如果您想停止显示在页面上的错误或警告消息,那么您可以在呼叫前加上@符号。

 @mysql_query($query);

通过查询,这样做通常是一个好主意,这样你就可以更好地了解正在发生的事情。

@mysql_query($query)
    or die('Invalid query: ' . mysql_error() . '<br />Line: ' . __LINE__ . '<br />File: ' . __FILE__ . '<br /><br />');

答案 3 :(得分:2)

如果您没有明确控制脚本正在处理的数据,则应使用错误处理。我倾向于经常使用它,例如在表单验证等地方。知道如何在代码中发现容易出错的位置需要一些练习:一些常见的是在返回值的函数调用之后,或者在处理来自数据库查询的结果时。你永远不应该假设函数的返回将是你期望的,你应该确保编码的预期。您不必使用try / catch块,尽管它们很有用。很多时候你可以使用简单的if / else检查。

错误处理与安全编码实践密切相关,因为有很多“错误”不会导致脚本崩溃。虽然不是严格意义上的错误处理本身,但是addbytes有一篇关于安全PHP编程基础知识的4篇系列文章,你可以找到HERE。关于诸如mysql_real_escape_stringRegular Expressions等主题的stackoverflow,还有很多其他问题可以在确认用户输入数据的内容方面非常强大。

答案 4 :(得分:2)

恕我直言的最佳做法是使用以下方法: 1.创建错误/异常处理程序 2.在app启动时启动它 3.从里面处理你的所有错误

<?php

class Debug {

    public static setAsErrorHandler() {
         set_error_handler(array(__CLASS__, '__error_handler'));
    }

public static function __error_handler($errcode, $errmsg, $errfile, $errline) {
       if (IN DEV) {
                print on screen
           }
           else if (IN PRO) {
                log and mail
           } 
    }

}

调试:: setAsErrorHandler();

&GT;

答案 5 :(得分:1)

您可以将其存储在日志中,而不是输出mysql_error。这样你可以跟踪错误(并且你不依赖于用户报告它),你可以进入并删除问题。

最好的错误处理是对用户透明的那种,让你的代码解决问题,不需要让那个用户同事。

答案 6 :(得分:1)

除了在代码中立即处理错误外,您还可以使用

http://us.php.net/manual/en/function.set-exception-handler.php

http://us.php.net/manual/en/function.set-error-handler.php

我发现设置自己的异常处理程序特别有用。发生异常时,您可以执行不同的操作,具体取决于它的异常类型。

例如:当mysql_connet调用返回FALSE时,我抛出new DBConnectionException(mysql_error())并以“特殊”方式处理它:记录错误,数据库连接信息(主机,用户名,密码) )甚至可能通过电子邮件发送开发团队通知他们数据库可能出现了问题

我使用它来赞美标准错误处理。我不建议过度使用这种方法

答案 7 :(得分:1)

使用@进行错误抑制非常慢。

答案 8 :(得分:0)

您还可以使用Google表单来捕获和分析异常,而无需维护数据库或可公开访问的服务器。有一个教程here可以解释这个过程。