1

在与我的团队发生争执后,因为我们对这种情况都有不同的看法。关闭 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 ?

所以我的整体问题?

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

4

3 回答 3

5

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

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

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

于 2013-06-16T16:39:33.573 回答
4

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

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

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

3 - 使用error_reporting = 2147483647PHP.INI 激活所有错误报告。这将使 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....

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

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

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

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

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

于 2013-06-16T16:03:17.473 回答
1

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

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

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

2 - 您可以使用默认的 php Error 和 Logging 函数和常量

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

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

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

于 2013-06-15T13:41:32.267 回答