抱歉,这不是一个确定的解决方案,但是经过几年的反复试验,我提出了以下做法,这些做法只是我自己的,并且效果很好:
1 - 永远不要使用 @ 来抑制错误。永远不要使用任何东西来盲目隐藏或忽略所有错误。所有错误都很重要,不应忽略任何错误。
2 - 按照 RafaSashi 的建议,打开错误记录并关闭显示错误。
3 - 使用error_reporting = 2147483647
PHP.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)
.
就是这样。错误处理并不简单,也没有直接的答案,但是有很多工具和良好实践可以帮助您选择最适合您的方法。