PHP中的错误处理

PHP中的错误处理,php,error-handling,Php,Error Handling,我对一些基本知识很熟悉,但我想了解更多的是PHP中何时以及为什么应该使用错误处理(包括抛出异常),特别是在实时网站或web应用程序上。是不是有些东西会被过度使用?如果是的话,过度使用是什么样子的?是否存在不应使用的情况?另外,在错误处理方面,有哪些常见的安全问题?非故意错误会停止脚本,这本身就是处理这些错误的一个很好的理由 通常,您可以使用Try-Catch块来处理错误 try { // Code that may error } catch (Exception $e) { /

我对一些基本知识很熟悉,但我想了解更多的是PHP中何时以及为什么应该使用错误处理(包括抛出异常),特别是在实时网站或web应用程序上。是不是有些东西会被过度使用?如果是的话,过度使用是什么样子的?是否存在不应使用的情况?另外,在错误处理方面,有哪些常见的安全问题?

非故意错误会停止脚本,这本身就是处理这些错误的一个很好的理由

通常,您可以使用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 />');
@mysql\u查询($query)
或者死('Invalid query:'.mysql_error()。
行:'.\u行:'.\u行:'.\u文件:'.\u文件:'.

);
您可以将其存储在日志中,而不是输出mysql\u错误。这样,您就可以跟踪错误(并且您不需要依赖用户来报告错误),并且可以进入并消除问题


最好的错误处理是对用户透明的,让您的代码来解决问题,不需要让用户参与。

如果您无法明确控制脚本正在处理的数据,则应使用错误处理。我倾向于经常使用它,例如在表单验证之类的地方。了解如何在代码中发现容易出错的位置需要一些实践:一些常见的位置是在返回值的函数调用之后,或者在处理数据库查询的结果时。您永远不应该假设函数的返回是您所期望的,并且您应该确保按照预期编写代码。您不必使用try/catch块,尽管它们很有用。很多时候,你可以通过简单的if/else检查来解决问题


错误处理与安全编码实践密切相关,因为有很多“错误”不会导致脚本崩溃。虽然addedbytes本身并不是严格的错误处理,但它有一个关于安全PHP编程基础的4篇系列文章,您可以找到这些文章。在stackoverflow上还有很多其他问题,例如和,这些问题在确认用户输入数据的内容方面非常有效。

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



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

例如:当一个
mysql\u-connet
调用返回
FALSE
时,我抛出一个
new-DBConnectionException(mysql\u-error())
并以“特殊”的方式处理它:记录错误、数据库连接信息(主机、用户名、密码)等,甚至可能向开发团队发送电子邮件,通知他们数据库可能确实有问题


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

有一点需要补充,那就是您必须将web应用程序中的任何错误记录到日志中。这样,正如杰夫·阿特伍德(Jeff“Coding Horror”Atwood)所建议的那样,当你的用户在你的应用程序中遇到问题时,你就会知道(而不是“问他们出了什么问题”)

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

  • 在数据库中创建一个“崩溃”表和一组用于报告错误的包装器类。我建议为崩溃设置类别(“阻塞”、“安全”、“PHP错误/警告”(vs异常)等)
  • 在所有错误处理代码中,确保记录错误。这样做的一致性取决于您构建API的程度(上述步骤)-如果操作正确,记录崩溃应该是微不足道的
额外信用:有时,您的崩溃将是数据库级崩溃:即数据库服务器关闭等。如果是这种情况,您的错误记录基础设施(如上)将失败(您无法将崩溃记录到数据库,因为日志试图写入数据库)。在这种情况下,我会在崩溃包装器类中将故障切换逻辑写入

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

所有这些听起来都有些过分,但相信我,这会让你的应用程序被认为是“稳定的”还是“不稳定的”有所不同。这种差异来自这样一个事实:所有应用程序一开始都是脆弱的/崩溃的,但那些了解应用程序所有问题的开发人员有机会实际修复它

IMHO的最佳实践是使用以下方法: 1.创建错误/异常处理程序 2.在应用程序启动时启动它 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
           } 
    }
}

Debug::setAsErrorHandler();

?>

粗略地说,错误是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);
不过,在一些情况下,代码是专门为处理错误而设计的。例如,在验证文档时,会引发警告。如果将错误转换为异常,它将在第一次失败后停止验证。有时这是您想要的,但在验证文档时,您可能实际上想要所有失败。在这种情况下,您可以临时安装一个收集错误的错误处理程序。这里有一个小片段,我已经用于此目的:

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());
}

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

您还可以使用谷歌表单捕获和分析异常,而无需维护数据库或可公开访问的服务器。有一个