对不起,这不是一个确定的解决方案,但经过几年的反复试验,我想出了以下做法,这些做法只是我自己的,并且效果很好:
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)。
就是这样。错误处理并不简单,也没有直接的答案,但有很多工具和良好做法可以帮助您选择最适合自己的方法。