2013-05-07 66 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); 
    } 
}