問(wèn)題描述
問(wèn)題:
尋找使用 PDO 進(jìn)行錯(cuò)誤處理的最佳實(shí)踐.我在網(wǎng)站、SO、書(shū)籍等上找到的選項(xiàng)
Finding best practice for error handling using PDO. The options I have found on websites, SO, books, etc.
- 很多網(wǎng)站都說(shuō)您應(yīng)該在
catch
塊中回顯錯(cuò)誤消息. - SO 上的大量用戶表示,由于安全風(fēng)險(xiǎn),您永遠(yuǎn)不應(yīng)回顯錯(cuò)誤消息.
- 其他人建議將其記錄到文檔根目錄之外的日志文件中.
- 有些使用錯(cuò)誤處理將其記錄到 SQL 表中.
有多種選項(xiàng),很容易被淹沒(méi)在您應(yīng)該使用的選項(xiàng)中.當(dāng)然,您可以使用 MVC 框架并讓它為您處理錯(cuò)誤日志,但是如果您不使用 MVC,它會(huì)是什么樣子.
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.
據(jù)我所知,開(kāi)發(fā)環(huán)境中的錯(cuò)誤處理應(yīng)該如下所示:
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
或者如果無(wú)法訪問(wèn) php.ini 文件:
Or if no access is available to the php.ini file:
error_reporting(-1);
ini_set("display_errors", 1);
在生產(chǎn)環(huán)境:
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On
或者如果無(wú)法訪問(wèn) php.ini 文件:
Or if no access is available to the php.ini file:
error_reporting(0);
以生產(chǎn)環(huán)境中的數(shù)據(jù)庫(kù)連接為例.
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;
}
?>
問(wèn)題:
- 在 PHP 中一般處理錯(cuò)誤的最佳做法是什么?
- 在 catch 塊中處理錯(cuò)誤的最佳做法是什么?
推薦答案
這是一個(gè)很好的問(wèn)題,但一開(kāi)始就有一個(gè)錯(cuò)誤的前提:您將 PDO 的錯(cuò)誤報(bào)告與站點(diǎn)范圍的錯(cuò)誤報(bào)告分開(kāi)了.這毫無(wú)意義:PDO 錯(cuò)誤在各個(gè)方面都與其他錯(cuò)誤相同 - 文件系統(tǒng)錯(cuò)誤、HTTP 錯(cuò)誤等等.因此,沒(méi)有理由建立僅限 PDO 的錯(cuò)誤報(bào)告.您只需要正確設(shè)置站點(diǎn)范圍的錯(cuò)誤報(bào)告.
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.
還有一個(gè)關(guān)于 php.ini 不可訪問(wèn)性的錯(cuò)誤假設(shè):您始終可以使用 ini_set() 函數(shù)設(shè)置任何配置指令.因此,將 error_reporting 設(shè)置為災(zāi)難性級(jí)別 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.
要回答您的其余問(wèn)題,您只需要一點(diǎn)常識(shí)即可.
To answer the rest of your questions all you need is a little common sense.
很多網(wǎng)站都說(shuō)您應(yīng)該在 catch 塊中回顯錯(cuò)誤消息.SO 上的大量用戶表示,由于安全風(fēng)險(xiǎn),您永遠(yuǎn)不應(yīng)該回顯錯(cuò)誤消息.
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.
你自己怎么看?向用戶顯示系統(tǒng)錯(cuò)誤消息有什么好處嗎?向惡意用戶展示系統(tǒng)內(nèi)部結(jié)構(gòu)有什么好處嗎?
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.
您對(duì)此有異議嗎?
有些使用錯(cuò)誤處理將其記錄到 SQL 表中.
Some use error handling to log it to a SQL table.
您不認(rèn)為將數(shù)據(jù)庫(kù)錯(cuò)誤記錄到數(shù)據(jù)庫(kù)中的想法很矛盾嗎?
Don't you think it's quite contradicting idea - to log database errors into database?
在 PHP 中一般處理錯(cuò)誤的最佳做法是什么?
What is the best practice for handling errors in general in PHP?
您已經(jīng)顯示了它:在開(kāi)發(fā)中顯示并在生產(chǎn)中登錄.所有這些都通過(guò)幾個(gè)簡(jiǎn)單的配置選項(xiàng)在站點(diǎn)范圍內(nèi)進(jìn)行控制.
You have shown it already: display in dev and log in prod. All is controlled site-wide through few simple configuration options.
在 catch 塊中處理錯(cuò)誤的最佳做法是什么?
What is the best practice for handling errors in the catch-block?
根本不要使用 try-catch 塊來(lái)報(bào)告錯(cuò)誤.您不會(huì)為應(yīng)用中的每個(gè)查詢編寫(xiě)帶有友好錯(cuò)誤消息的 catch 塊strong>,正如另一個(gè)答案中所建議的那樣,是嗎?
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);
現(xiàn)在回答您在評(píng)論中提出的問(wèn)題.
Now to the question you voiced in the comment.
自定義錯(cuò)誤屏幕是另一回事,您的代碼尤其糟糕.它既不應(yīng)該是 404 錯(cuò)誤,也不應(yīng)該使用 HTTP 重定向(這對(duì) SEO 來(lái)說(shuō)非常糟糕).
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).
要?jiǎng)?chuàng)建自定義錯(cuò)誤頁(yè)面,您必須使用您的網(wǎng)絡(luò)服務(wù)器功能(首選)或 PHP 腳本中的錯(cuò)誤處理程序.
To create a custom error page you have to use either your web-server features (preferred) or an error handler in PHP script.
當(dāng)遇到致命錯(cuò)誤(未捕獲異常就是其中之一)時(shí),PHP 響應(yīng)的不是 200 OK HTTP 狀態(tài)而是 5xx 狀態(tài).每個(gè)網(wǎng)絡(luò)服務(wù)器都可以捕獲此狀態(tài)并顯示相應(yīng)的錯(cuò)誤頁(yè)面.例如.對(duì)于 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
你可以寫(xiě)任何你想要的借口.
where you can write whatever excuses you want.
或者你可以在 PHP 中設(shè)置一個(gè)自定義的錯(cuò)誤處理程序來(lái)處理所有的 PHP 錯(cuò)誤,一個(gè)例子可以在我寫(xiě)的關(guān)于這個(gè)問(wèn)題的文章中看到: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.
這篇關(guān)于使用 PDO 處理錯(cuò)誤的最佳實(shí)踐的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!