如何正确处理PDO连接错误?



出于安全原因,我尝试处理或捕获PHP/MySQL可能的错误,并想知道我做得是否正确。 第一种情况:我将其用作函数,并在需要数据库连接时始终调用它。 第二种情况:我不知道如何处理。我把所有准备好的陈述都放在if条件下,但这很尴尬。 那$stmt->execute呢?这也可能会失败,并且在 if 条件下处理这个问题真的会让人感到困惑。 我希望有更好的方法。

第一:

function pdo () {
try {
$pdo = new PDO('mysql:host=localhost;dbname=dbname', 'user', 'pw');
}
catch(PDOException $e) {
header("Location: handle_error.php");
exit;
}
return ($pdo);
}

第二:

if ($stmt = $pdo->prepare("SELECT a FROM b WHERE c = :c")) {
$stmt->execute(array(':c' => $c));
$result = $stmt->fetch();
echo 'All fine.';
}
else {
echo 'Now we have a problem.';
}

您当前的代码存在一些缺陷。让我给你几个指示。

您不需要
  1. 您创建的函数,至少不需要当前形式的函数。每次调用此函数时,它都会创建一个新的 PDO 对象,这可能会妨碍脚本的性能。理想情况下,您希望在整个脚本执行过程中只有一个连接。

  2. 创建新的 PDO 连接时,您需要记住 3 件事:设置正确的连接字符集、启用错误报告和禁用模拟准备。

    • 正确的字符集很重要。没有它,您的数据可能会损坏,甚至使您容易受到SQL注入的影响。建议的字符集是utf8mb4
    • 启用错误报告可省去手动检查每个函数调用是否失败的麻烦。你只需要告诉PHP在发生错误时触发异常,并找到一种合适的方法来记录服务器上的错误(阅读更多:我的PDO语句不起作用(
    • 默认情况下启用模拟准备,但事实是没有它们会更好。如果您的数据库支持本机预准备语句,并且大多数都支持,请改用它们。

    完整代码应如下所示:

    $options = [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
    ];
    $pdo = new PDO('mysql:host=localhost;dbname=dbname;charset=utf8mb4', 'user', 'pw', $options);
    
  3. 不要捕获异常,除非您知道如何处理它们并且肯定需要这样做。例外最好留下;让 PHP 将它们与其他异常/错误/警告一起处理。毕竟,为什么要只对PHP异常例外呢?所有 PHP 错误都应以相同的方式处理。无论您做什么,都不会在屏幕上手动打印(包括dieexitechovar_dump(错误消息。如果这样的代码进入生产环境,这是一个巨大的安全问题。

如果您的 PDO 连接设置为在出错时引发异常,则永远不需要使用if语句来检查prepare()execute()的返回代码。

最新更新