问题:
查找使用PDO处理错误的最佳实践。我在网站、SO、书籍等上找到的选项
- 许多网站表示,您应该在
catch
块中回显错误消息 - SO上的大量用户表示,由于存在安全风险,您永远不应该回显错误消息
- 其他人则建议将其记录到文档根目录之外的日志文件中
- 有些使用错误处理将其记录到SQL表中
有了大量的选项,很容易淹没在你应该使用的选项中。当然,你可以使用MVC框架,让它为你处理错误日志,但如果你不使用MVC,它会是什么样子。
据我所知,在开发环境中,错误处理应该如下所示:
display_errors = On
display_startup_errors = On
error_reporting = -1
log_errors = On
或者,如果无法访问php.ini文件:
error_reporting(-1);
ini_set("display_errors", 1);
在生产环境中:
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On
或者,如果无法访问php.ini文件:
error_reporting(0);
以生产环境中的数据库连接为例。
代码:
<?php
// Error handling
error_reporting(0);
// Get credentials from outside document root
require_once('../settings.php');
// Tests connection to database
try {
$dbh = new PDO(
sprintf(
'mysql:host=%s;dbname=%s;port=%s;charset=%s',
$settings['host'],
$settings['name'],
$settings['port'],
$settings['charset']
),
$settings['username'],
$settings['password']
);
// Prevents emulated prepares and activates error handling
// PDO::ERRMODE_EXCEPTION
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
// Catches errors raised by PDO
catch (PDOException $e) {
// Prints error messages to file
file_put_contents('/home/ubuntu/errors.log', 'Error: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
// Shows generic error message to user
header('Location: 404.php');
exit;
}
?>
问题:
- 在PHP中处理错误的最佳实践是什么
- 处理catch块中错误的最佳实践是什么
这是一个很好的问题,但一开始有一个错误的前提:您将PDO的错误报告与站点范围的错误报告分开。这毫无意义:PDO错误在各个方面都与其他错误相同——文件系统错误、HTTP错误等等。因此,没有理由只建立PDO错误报告。您所需要的只是正确设置站点范围的错误报告。
关于php.ini的不可访问性,还有一个错误的假设:您总是可以使用ini_set((函数设置任何配置指令。因此,将error_reporting设置为灾难性级别0并不是一个单一的原因。
要回答剩下的问题,你只需要一点常识。
许多网站表示,您应该在捕获块中回显错误消息。SO上的大量用户表示,由于存在安全风险,您永远不应该回显错误消息。
你自己怎么想?向用户显示系统错误消息有什么好处吗?向恶意用户展示系统内部有什么好处吗?
其他人则建议将其记录到文档根目录之外的日志文件中。
你对此有什么反对意见吗?
有些使用错误处理将其记录到SQL表中。
你们不认为将数据库错误记录到数据库中是很矛盾的想法吗?
在PHP中处理错误的最佳实践是什么?
您已经展示了这一点:在dev中显示,在prod中登录。所有这些都是通过几个简单的配置选项在站点范围内控制的。
处理catch块中错误的最佳实践是什么?
根本不使用try-catch块进行错误报告您不会像另一个答案中所建议的那样,为应用程序中的每个查询编写带有友好错误消息的catch块,是吗?
因此,您的代码必须是
<?php
// Error handling
error_reporting(-1);
ini_set('display_errors',0);
ini_set('log_errors',1);
// Get credentials from outside document root
require_once('../settings.php');
// Tests connection to database
$dbh = new PDO(
sprintf(
'mysql:host=%s;dbname=%s;port=%s;charset=%s',
$settings['host'],
$settings['name'],
$settings['port'],
$settings['charset']
),
$settings['username'],
$settings['password']
);
// Prevents emulated prepares and activates error handling
// PDO::ERRMODE_EXCEPTION
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
现在来谈谈你在评论中提出的问题。
自定义错误屏幕是一个非常不同的问题,你的代码特别糟糕。它既不应该是404错误,也不应该使用HTTP重定向(这对SEO来说非常糟糕(。
要创建自定义错误页面,您必须使用web服务器功能(首选(或PHP脚本中的错误处理程序。
当遇到致命错误(未捕获的异常就是其中之一(时,PHP的响应不是200 OK HTTP状态,而是5xx状态。每个web服务器都可以捕捉到这种状态并显示相应的错误页面。例如,对于Apache,它将是
ErrorDocument 503 server_error.html
在那里你可以写下你想要的任何借口。
或者你可以在PHP中设置一个自定义的错误处理程序,它也可以处理所有的PHP错误,在我写的关于这个问题的文章中可以看到一个例子:try..的(im(正确使用。。接住