2013-05-07 64 views
3

從關於intertubes的教程中,我學到了一些關於PDO查詢的知識。本教程使用try/catch和查詢基本上是這樣構造的:PDO錯誤處理

try { 
    $dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $user, $pass); 

    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 

    $stmt = $dbh->prepare("UPDATE users yada yada yadda"); 

    $stmt->bindParam(':param1', $param1, PDO::PARAM_INT); 
    $stmt->bindParam(':param2', $param2, PDO::PARAM_INT); 

    $stmt->execute(); 

} 

catch(PDOException $e) 
{ 
    echo $e->getMessage(); 
} 

這當然回聲mysql錯誤在屏幕上。並不是說我打算進行糟糕的查詢,但我不喜歡在屏幕上回顯錯誤的想法,弄清楚如果攻擊者試圖誘發所述錯誤並嘗試向他們學習某些東西。

有沒有更好的方法來做到這一點,以便任何錯誤轉到日誌文件,或者我真的沒有什麼可怕的,因爲綁定參數消除了任何SQL注入的風險?

+0

http://php.net/manual/en/function.error-log.php – CBroe 2013-05-07 08:38:45

回答

1

是否有更好的方法來做到這一點

是的,沒錯!

這顯然是錯誤的方式來處理本教程教你的PDO錯誤。
所以,只要擺脫這些try..catch命令 - 就這些。

這樣你就可以像處理其他PHP錯誤一樣處理PDO異常。因此,如果發生查詢錯誤,您的腳本將被暫停並記錄錯誤(如果您告訴PHP如此)。
要告訴PHP所以,你必須設置log_errors INI指令1 告訴PHP不顯示在屏幕上的錯誤,設置display_errors INI指令0(開發服務器上,你不妨雖然扭轉他們)

4

該教程是正確的,因爲您想使用try..catch塊來捕獲可能導致錯誤的代碼,並降低您加載的任何內容。所以,如果你有一些依賴於這個代碼執行的代碼,你會希望將它包含在你的try部分中。如果你絕對需要這段代碼來執行你正在創建的任何工作,那麼你可能想要捕捉錯誤並將用戶重定向到某種類型的錯誤頁面。

如果使用the php error log function然後代替

echo $e->getMessage(); 

您可以使用

error_log($e->getMessage(),0); 

從PDO直接發送錯誤信息到PHP錯誤日誌。如果您不知道錯誤日誌的位置,請在you can check out this link之前指定一個指向它的指針,如果您正在運行* nix系統。如果你正在運行windows,應該有一個配置文件可以告訴你。或者,您可以檢查php ini文件中指向的位置,以確保找到日誌。

+0

爲什麼downvote? – EdgeCaseBerg 2013-05-07 15:57:05

+1

有沒有意義downvoting這個答案,因爲它是一個完全有效的答案,我upvoting它 – 2013-06-12 12:46:14

0

那麼,我的答案可能不是最佳做法,所以請將它留給最後一個選項。但對於我的情況,它完美的作品。

但是,無論如何,無論您在PDO :: ATTR_ERRMODE中設置了什麼,PDO :: __構造都會給你一個例外。我不知道他們爲什麼設計它的行爲如此。

我解決這個問題的方法是創建一個代碼區,我稱之爲調試關鍵部分(意味着您需要非常小心代碼部分),本節中的任何錯誤都不會直接輸出給用戶。

這是我爲我的框架使代碼:

private function doPDOConnect($dbIndex, &$DBInfo, &$error) { 
    $dbh = null; 
    $successed = false; 

    if (!isset($this->connectedDB[$dbIndex])) { 

     // Enter Critical Section so no error below belowing code will cause error output, but the error still in log though 
     facula::core('debug')->criticalSection(true); 

     try { 
      $dbh = new PDO($DBInfo['Driver'] . ':' . $DBInfo['Connection'] . '=' . $DBInfo['Host'] . ';dbname=' . $DBInfo['Database'], $DBInfo['Username'], $DBInfo['Password'], array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING, PDO::ATTR_TIMEOUT => $DBInfo['Timeout'])); // ATTR_ERRMODE => PDO::ERRMODE_WARNING. or we will cannot get anything even error happens 

      $dbh->facula_prefix = $DBInfo['Prefix']; 
      $dbh->facula_index = $dbIndex; 
      $dbh->facula_connection = $DBInfo; // In order you want to reconnect this specify database after connection lost etc, remove if you worry about the security issue. 

      $successed = true; 
     } catch (PDOException $e) { 
      $error = $e->getMessage(); // If any error, catch it, to &$error. 
     } 

     // Exit Critical Section, restore error caught 
     facula::core('debug')->criticalSection(false); 

     if ($successed) { 
      return $this->connectedDB[$dbIndex] = $dbh; 
     } 
    } else { 
     return $this->connectedDB[$dbIndex]; 
    } 

    return false; 
} 
你的情況

所以,你可以代替我的光斑::核心(「調試」) - > CriticalSection的到的display_errors關/開來處理錯誤顯示處理正確。

例如:

$display_error_status = ini_get('display_errors'); 

function criticalSection($entered) { 
    global $display_error_status; 

    if ($entered) { 
     ini_set('display_errors', '0'); 
    } else { 
     ini_set('display_errors', $display_error_status); 
    } 
}