kex*_*eam 5 php mysql error-handling pdo database-connection
问题:
找到使用PDO进行错误处理的最佳实践.我在网站,SO,书籍等上找到的选项.
catch块中回应你的错误信息.有了很多选项,很容易淹没你应该使用的选项.当然,您可以使用MVC框架并让它为您处理错误日志记录,但如果您不使用MVC,它会是什么样子.
据我所知,错误处理应该像开发环境中的以下内容:
display_errors = On
display_startup_errors = On
error_reporting = -1
log_errors = On
Run Code Online (Sandbox Code Playgroud)
或者,如果php.ini文件没有可用的访问权限:
error_reporting(-1);
ini_set("display_errors", 1);
Run Code Online (Sandbox Code Playgroud)
在生产环境中:
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On
Run Code Online (Sandbox Code Playgroud)
或者,如果php.ini文件没有可用的访问权限:
error_reporting(0);
Run Code Online (Sandbox Code Playgroud)
以生产环境中的数据库连接为例.
码:
<?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;
}
?>
Run Code Online (Sandbox Code Playgroud)
题:
这是一个非常好的问题,但是一开始就有一个错误的前提:您将 PDO 的错误报告与站点范围的错误报告分开。这毫无意义:PDO 错误在各个方面都与其他错误相同 - 文件系统错误、HTTP 错误等等。因此,没有理由建立仅 PDO 的错误报告。您所需要的只是正确设置站点范围的错误报告。
关于 php.ini 不可访问性还有一个错误的假设:您始终可以使用 ini_set() 函数设置任何配置指令。因此,这里并不是将 error_reporting 设置为灾难性级别 0 的唯一原因。
要回答您的其余问题,您所需要的只是一点常识。
许多网站表示您应该在 catch 块中回显错误消息。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);
Run Code Online (Sandbox Code Playgroud)
现在回答您在评论中提出的问题。
自定义错误屏幕是一个非常不同的问题,并且您的代码尤其糟糕。它既不应该是 404 错误,也不应该使用 HTTP 重定向(这对 SEO 非常不利)。
要创建自定义错误页面,您必须使用 Web 服务器功能(首选)或 PHP 脚本中的错误处理程序。
当遇到致命错误(未捕获的异常就是其中之一)时,PHP 不会以 200 OK HTTP 状态响应,而是以 5xx 状态响应。每个网络服务器都可以捕获此状态并显示相应的错误页面。例如对于 Apache 来说是
ErrorDocument 503 server_error.html
Run Code Online (Sandbox Code Playgroud)
在那里你可以写任何你想要的借口。
或者,您可以在 PHP 中设置一个自定义错误处理程序,它也可以处理所有 PHP 错误,可以在我就此事撰写的文章中看到一个示例:The (im)proper use of try..catch。