【问题标题】:Turn off or handle errors within a production environment?在生产环境中关闭或处理错误?
【发布时间】:2013-06-15 12:47:44
【问题描述】:

在与我的团队发生争执后,因为我们对这种情况都有不同的看法。什么时候关闭 PHP 错误消息,或者禁止一些抛出警告的函数,无论出于何种原因,通知都是可以接受的。 .

我知道每个人都说您应该在生产环境中关闭 error_reporting,但这可能会导致一些无法解决的问题。因此,任何事情都不会得到解决。 PHP 带有许多不同的方法来控制错误消息。例如:

$Var = "Variable Is Set";

if (@$Var){ echo $Var; }

结束:

if (isset($Var)){ echo $Var; }

因为我们有一个 set 变量,所以这将成功地回显.. 而如果我们没有 set 变量,这会引发一个通知.. 那么使用哪一个呢? isset 还是错误抑制?

在生产环境中,哪一个更容易被接受?

error_reporting(0);

以上将关闭所有类型的 PHP 错误报告,即使遇到问题也不给出错误消息。因此,在某些情况下,由于消息被破坏,这可能会导致代码因未知原因停止工作

或:

set_error_handler("");

上面启用了一个自定义错误处理程序,它可以用来优雅地向用户显示错误,并使管理人员能够记录详细的警告。但话又说回来,据我所知,error_handler 在致命时不会被调用错误被触发?

所以我的整体问题?

处理生产环境中的错误还是一般将其关闭?我猜这归结为最佳实践和偏好。但这让我和我的团队感到困惑,以至于产生了分歧。

【问题讨论】:

标签: php


【解决方案1】:

永远不会完全关闭错误报告。你关闭错误显示。在开发过程中直接将错误转储到屏幕上是必要的(除非您有其他方法会在您的脸上抛出所有错误),在生产中您想要相同的错误 reporting 但不是输出可见错误,而是您想要它只记录它们。这一切都可以使用 PHP 的错误报告配置设置来完成。

如果您想要特殊的自定义错误处理/记录,请使用自定义错误处理程序。

至于@,您在编写应用程序时绝不会根据您所依赖的行为产生实际错误。您以不会触发错误的方式编写所有内容。只有在无法避免可能的错误时才使用@,因为您无法以任何其他方式编写它,并且您预期会出现错误并正在处理它;那么你所做的一切都是为了抑制不可避免的错误信息。

【讨论】:

    【解决方案2】:

    对不起,这不是一个确定的解决方案,但经过几年的反复试验,我想出了以下做法,这些做法只是我自己的,并且效果很好:

    1 - 永远不要使用 @ 来抑制错误。永远不要使用任何东西来盲目隐藏或忽略所有错误。所有错误都很重要,不应忽略任何错误。

    2 - 按照 RafaSashi 的建议,打开错误记录并关闭显示错误。

    3 - 通过在 PHP.INI 中使用 error_reporting = 2147483647 激活所有错误报告。这将使 PHP 对您可能做错的任何事情都非常挑剔,帮助您了解更多信息并及时了解未来的语言弃用和更改。

    4 - 您还可以创建自己的错误日志记录,以您想要的方式准确记录您想要的内容。查找error_log() 的手册。如果您使用它,您甚至可以关闭 looging,然后手动开始记录,这样您就可以完全控制 PHP 的错误记录系统。

    5 - 我在所有 PHP 代码中都使用 OOP,所以我在所有地方都使用异常,我建议每个人都这样做。它们比简单的错误处理早了几光年。使用此代码拦截代码中的所有错误并将它们作为异常抛出:

    set_error_handler('ErrorHandler');
    function ErrorHandler($Code, $Message)
    {
      throw new Exception($Message, $Code);
    }
    

    6 - 不向用户显示任何错误是毫无意义的。有些错误应该显示,有些应该隐藏,有些应该显示为一般问题(不要告诉用户确切的问题是什么)。

    a) 应显示的错误:由用户引起的一切,例如无效的表单输入或错误行为。这很明显,但应该提及。

    b) 应该隐藏的错误:只隐藏您的代码可以处理和纠正的错误。例如,你可以做一个 DB 连接,如果它失败了,你可以再试一次。如果第二次尝试成功,请继续,没有人会知道第一次尝试失败。如果需要,只需使用error_log() 记录它。有时,变量还不存在,因此请使用isset() 进行检查,并在需要时对其进行初始化。也无需将此报告为错误。

    c) 应显示为一般错误:大多数错误都属于此类别。您不会向用户显示诸如 PHP 内存耗尽、SMTP 服务器离线或数据库连接被拒绝之类的信息。只需学习如何使用 try 包装危险代码,使用 catch 捕获任何错误,并将消息转换为可以显示给用户的内容。示例:

    try
    {
      // Dangerous code ahead: we will try to connect to the database, but it 
      // can be offline.
      $mysqli = new mysqli("localhost", "user", "password", "database");
    }
    catch(Exception $e)
    {
      // If we're here, something bad happened during connection. Let's handle it.
    
      // Notify staff, log error, do anything you can to get someone to quickly 
      // check the issue.
      SendMailAdmin("Database connection Error, check ASAP.");
      error_log("Database connection Error, check ASAP.");
    
      // And show the user some message. You don't need to tell him about any 
      // detail regarding what truly caused the error.
      die("A problem occurred in our servers. Our technical staff has been notified, 
          please try again in a few minutes.");
    }
    
    // If we're here, everything worked fine, so do your DB query and so on....
    

    除了die(),您可以使用您认为合适的方法:作为另一个异常重新抛出,将标头重定向到一般错误消息或任何您想要的。

    7 - 这是更高级的,但您也可以这样做:创建您自己的异常层次结构,如下所示:

    class MVXException extends Exception {}
        class ExMVXDB extends MVXException {}
          class ExMVXDBRead extends ExMVXDB { }
          class ExMVXDBWrite extends ExMVXDB { }
          class ExMVXDBNotFound extends ExMVXDB { }
    

    这是我自制框架中异常树的简化。这样做的好处是,如果您执行catch(ExMVXDB $e),您将捕获所有数据库错误。但是如果你只想捕获一个数据写入操作,你可以做一个catch(ExMVXDBWrite $e)

    就是这样。错误处理并不简单,也没有直接的答案,但有很多工具和良好做法可以帮助您选择最适合自己的方法。

    【讨论】:

      【解决方案3】:

      1 - 您可以关闭 display_errors 并打开 log_errors

      @ini_set('log_errors','On');
      
      @ini_set('display_errors','Off');
      

      2 - 您可以使用默认的 php 错误和日志记录函数和常量

      见:http://www.w3schools.com/php/php_ref_error.asp

      3 - 您可以使用 PHP 文件系统实现自己的一组错误和日志记录功能

      见:http://www.w3schools.com/php/php_ref_filesystem.asp

      【讨论】:

      • W3Schools 是一个糟糕的资源。我建议改用官方的 PHP 文档。
      • 这听起来很刺耳。这对没有经验的用户来说有点有用。虽然我知道你给出的方法。 -1 使用 W3School,因为它不值得信任
      猜你喜欢
      • 2020-10-19
      • 1970-01-01
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 2011-09-08
      • 1970-01-01
      • 2016-11-24
      • 2016-05-19
      相关资源
      最近更新 更多