问题:
寻找使用 PDO 进行错误处理的最佳实践.我在网站、SO、书籍等上找到的选项
Finding best practice for error handling using PDO. The options I have found on websites, SO, books, etc.
catch
块中回显错误消息.有多种选项,很容易被淹没在您应该使用的选项中.当然,您可以使用 MVC 框架并让它为您处理错误日志,但是如果您不使用 MVC,它会是什么样子.
With a multitude of options, it gets quite easy to drown into what option you should be using. Of course you could use a MVC framework and let it handle error logging for you, but how would it look like if you are not using MVC.
据我所知,开发环境中的错误处理应该如下所示:
As I have understood it error handling should like the following in development environment:
display_errors = On
display_startup_errors = On
error_reporting = -1
log_errors = On
或者如果无法访问 php.ini 文件:
Or if no access is available to the php.ini file:
error_reporting(-1);
ini_set("display_errors", 1);
在生产环境:
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On
或者如果无法访问 php.ini 文件:
Or if no access is available to the php.ini file:
error_reporting(0);
以生产环境中的数据库连接为例.
To take an example of a database connection in production environment.
代码:
<?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;
}
?>
问题:
这是一个很好的问题,但一开始就有一个错误的前提:您将 PDO 的错误报告与站点范围的错误报告分开了.这毫无意义:PDO 错误在各个方面都与其他错误相同 - 文件系统错误、HTTP 错误等等.因此,没有理由建立仅限 PDO 的错误报告.您只需要正确设置站点范围的错误报告.
That's a very good question, but there is one wrong premise at the very beginning: you are taking error reporting for PDO separated from site-wide error reporting. Which makes very little sense: PDO errors in every way are the same as other errors - filesystem errors, HTTP errors, and so on. Thus, there is no reason in establishing PDO-only error reporting. All you need is to properly set site-wide error reporting.
还有一个关于 php.ini 不可访问性的错误假设:您始终可以使用 ini_set() 函数设置任何配置指令.因此,将 error_reporting 设置为灾难性级别 0 的原因不止于此.
There is also one wrong assumption regarding php.ini inaccessibility: you can always set any configuration directive using ini_set() function. Thus, here is not a single reason in setting error_reporting to disastrous level of 0.
要回答您的其余问题,您只需要一点常识即可.
To answer the rest of your questions all you need is a little common sense.
很多网站都说您应该在 catch 块中回显错误消息.SO 上的大量用户表示,由于安全风险,您永远不应该回显错误消息.
A great number of websites say you should echo your error messages in your catch block. A large number of users on SO say that you should never echo error messages due to security risks.
你自己怎么看?向用户显示系统错误消息有什么好处吗?向恶意用户展示系统内部结构有什么好处吗?
What you think yourself? Does it any good showing system error messages to user? Does it any good showing system internals to a malicious user?
其他人建议将其记录到文档根目录之外的日志文件中.
Others are recommending logging it to a log file outside the document root.
您对此有异议吗?
有些使用错误处理将其记录到 SQL 表中.
Some use error handling to log it to a SQL table.
您不认为将数据库错误记录到数据库中的想法很矛盾吗?
Don't you think it's quite contradicting idea - to log database errors into database?
在 PHP 中一般处理错误的最佳做法是什么?
What is the best practice for handling errors in general in PHP?
您已经显示了它:在开发中显示并在生产中登录.所有这些都通过几个简单的配置选项在站点范围内进行控制.
You have shown it already: display in dev and log in prod. All is controlled site-wide through few simple configuration options.
在 catch 块中处理错误的最佳做法是什么?
What is the best practice for handling errors in the catch-block?
根本不要使用 try-catch 块来报告错误.您不会为应用中的每个查询编写带有友好错误消息的 catch 块strong>,正如另一个答案中所建议的那样,是吗?
NOT to use try-catch block for error reporting at all. You aren't going to write a catch block with a friendly error message for the every query in your app, as it's suggested in the other answer, are you?
因此你的代码必须是
<?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);
现在回答您在评论中提出的问题.
Now to the question you voiced in the comment.
自定义错误屏幕是另一回事,您的代码尤其糟糕.它既不应该是 404 错误,也不应该使用 HTTP 重定向(这对 SEO 来说非常糟糕).
A custom error screen is a very different matter and your code is especially bad with it. Neither it should be a 404 error nor an HTTP redirect have to be used (thats very bad for SEO).
要创建自定义错误页面,您必须使用您的网络服务器功能(首选)或 PHP 脚本中的错误处理程序.
To create a custom error page you have to use either your web-server features (preferred) or an error handler in PHP script.
当遇到致命错误(未捕获异常就是其中之一)时,PHP 响应的不是 200 OK HTTP 状态而是 5xx 状态.每个网络服务器都可以捕获此状态并显示相应的错误页面.例如.对于 Apache,它将是
When encountering a fatal error (and uncaught exception is one), PHP responds not with 200 OK HTTP status but with 5xx status. And every web-server can catch this status and show an according error page. E.g. for Apache it would be
ErrorDocument 503 server_error.html
你可以写任何你想要的借口.
where you can write whatever excuses you want.
或者你可以在 PHP 中设置一个自定义的错误处理程序来处理所有的 PHP 错误,一个例子可以在我写的关于这个问题的文章中看到:try..catch 的(im)正确使用.
Or you can set up a custom error handler in PHP which would handle all PHP errors as well, an example can be seen in the article I wrote on the matter: The (im)proper use of try..catch.
这篇关于使用 PDO 处理错误的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!