簡體   English   中英

關閉或處理生產環境中的錯誤?

[英]Turn off or handle errors within a production environment?

在與我們的團隊爭執之后,因為我們對這種情況都有不同的看法..什么時候可以關閉PHP錯誤消息或抑制某些引發警告的函數,無論出於何種原因,都應注意。

我知道每個人都說您應該在生產環境中關閉error_reporting,但是這可能會導致一些復雜性,而這些復雜性將不會得到解決。 PHP附帶許多不同的方法來控制錯誤消息。例如:

$Var = "Variable Is Set";

if (@$Var){ echo $Var; }

過度:

if (isset($Var)){ echo $Var; }

因為我們有一個set變量,所以它會成功地回顯。如果我們沒有set變量,這將引發一個提示。那么使用哪個變量呢? isset或錯誤抑制?

在生產環境中,哪個更適合使用?

error_reporting(0);

上面的代碼將關閉所有類型的PHP錯誤報告,即使遇到任何情況也不會給出錯誤消息。 因此在某些情況下,這可能會導致代碼損壞,由於消息被破壞,代碼由於未知原因而停止工作

要么:

set_error_handler("");

上面的代碼啟用了一個自定義錯誤處理程序,該錯誤處理程序可用於向用戶正常顯示錯誤,並使管理人員可以記錄詳細警告。但是,再次提醒您,當觸發致命錯誤時,不會調用我所知的error_handler。 ?

所以我的總體問題?

處理生產環境中的錯誤還是一般將其關閉? 我認為這歸結為最佳做法和偏好。但這使我和我的團隊感到困惑,甚至是意見分歧。

永遠不會簡單地完全關閉錯誤報告。 確實要關閉錯誤顯示 在開發過程中,必須將錯誤直接轉儲到屏幕上(除非您有其他方法可以將所有錯誤丟在臉上),在生產中,您需要相同的錯誤報告,而不是輸出可見的錯誤,而只希望記錄錯誤。 所有這些都可以使用PHP的錯誤報告配置設置來完成。

如果要特殊的自定義錯誤處理/記錄,請使用自定義錯誤處理程序。

至於@ ,您永遠不會以產生實際錯誤(取決於您的行為)的方式來編寫應用程序。 您以不會觸發錯誤的方式編寫所有內容。 僅在無法避免可能的錯誤的情況下才使用@ ,因為您無法以其他任何方式編寫它,並且您期望出現錯誤並正在處理它; 那么您要做的就是抑制不可避免的錯誤消息。

抱歉,這不是一個確定的解決方案,但是經過幾年的反復試驗,我提出了以下實踐,這些實踐只是我自己的,並且運行良好:

1-切勿使用@來抑制錯誤。 切勿使用任何東西盲目隱藏或忽略所有錯誤。 所有錯誤都很重要,不應忽略任何錯誤。

2-按照RafaSashi的建議執行操作,打開錯誤記錄並關閉顯示錯誤。

3-通過在PHP.INI中使用error_reporting = 2147483647激活所有錯誤報告。 這將使PHP非常挑剔您可能做錯的任何事情,從而幫助您了解更多信息並及時了解將來的語言棄用和更改。

4-您還可以創建自己的錯誤日志記錄,以准確記錄所需的內容和所需的方式。 在手冊中查找error_log() 如果使用它,甚至可以關閉清除,然后手動開始記錄,這將使您完全控制PHP的錯誤記錄系統。

5-我在所有PHP代碼中都使用OOP,因此我在所有地方都使用了異常,因此我建議所有人都使用異常。 它們比簡單的錯誤處理快了幾年。 使用此代碼來攔截代碼中的所有錯誤並將它們作為異常拋出:

set_error_handler('ErrorHandler');
function ErrorHandler($Code, $Message)
{
  throw new Exception($Message, $Code);
}

6-不向用戶顯示任何錯誤完全是胡說八道。 應該顯示一些錯誤,應該隱藏一些錯誤,並且應該將某些錯誤顯示為一般性問題(請不要告訴用戶確切的問題是什么)。

a) 應該顯示的錯誤:由用戶引起的所有錯誤 ,例如無效的表格輸入或錯誤的行為。 這是很明顯的,但應該提到。

b) 應該隱藏的錯誤僅隱藏代碼可以處理和糾正的錯誤。 例如,您可以進行數據庫連接,如果連接失敗,則可以重試。 如果第二次嘗試成功,請繼續,沒有人會知道第一次嘗試失敗。 如果需要,只需使用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(ExMVXDB $e) ,則將捕獲所有DB錯誤。 但是,如果您只想捕獲數據寫入操作,則可以執行catch(ExMVXDBWrite $e)

而已。 錯誤處理並不簡單,沒有直接的答案,但是有很多工具和良好實踐可以幫助您選擇最適合自己的方法。

1-您可以關閉display_errors並打開log_errors

@ini_set('log_errors','On');

@ini_set('display_errors','Off');

2-您可以使用默認的php錯誤和日志記錄功能及常量

請參閱: http : //www.w3schools.com/php/php_ref_error.asp

3-您可以使用PHP Filesystem實現自己的錯誤和日志記錄功能集

請參閱: http//www.w3schools.com/php/php_ref_filesystem.asp

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM