web-dev-qa-db-ja.com

PDO例外の質問-それらをキャッチする方法

PDOを使用して、データベースのWebサイトインターフェイスを書き換えています。以前はmysql拡張を使用していましたが、エラー処理に煩わされることは一度もありませんでした。私が持っていたいくつかのエラーハンドラーは基本的にコピーアンドペーストでした。

今、私はこれを正しく行いたいと思います。ただし、私が希望するエラー(MySQLの「Duplicate Entry」、「Null Value」などのエラー)をキャッチするのに問題があります。私の発言のどれだけをtryブロックに含める必要がありますか?それはすべてそこにあるべきですか?私はInclude()を使用して自分のDB(独自のエラー処理を行う)に接続しているため、このコードでエラーが発生するのはクエリの実行のみです。次のコードを実行したときにエラーがキャッチされない理由を理解できません。

try {
  $stmt = $db->prepare("INSERT INTO tbl_user (id, name, password, question, answer)    VALUES (NULL, :name, :password, :question, :answer)");
  $stmt->bindValue(":name", $_POST['name']);
  $stmt->bindValue(":password", $_POST['password']);
  $stmt->bindValue(":question", $_POST['question']);
  $stmt->bindValue(":answer", $_POST['answer']);
  $stmt->execute();
  echo "Successfully added the new user " . $_POST['name'];
} catch (PDOException $e) {
  echo "The user could not be added.<br>".$e->getMessage();
}

だから私の質問:それらすべてがtryブロックにある必要がありますか?実行をtryブロックに入れることはできますか?エラーをキャッチする必要がありますDuplicate value "John" in key "name"ですが、代わりに成功メッセージが表示されます。 (2人の「John」ユーザーを追加しようとした場合)。 PHPMyAdminをチェックインしました。インデックスは一意であり、このコードを使用しないだけで、期待どおりにエラーをスローします。

19
StuckAtWork

ドキュメントをご覧ください。しかし、何も見つからない場合は、別のキャッチを追加できます。

<?php
try {
  $stmt = $db->prepare("INSERT INTO tbl_user (id, name, password, question, answer)    VALUES (NULL, :name, :password, :question, :answer)");
  $stmt->bindValue(":name", $_POST['name']);
  $stmt->bindValue(":password", $_POST['password']);
  $stmt->bindValue(":question", $_POST['question']);
  $stmt->bindValue(":answer", $_POST['answer']);
  $stmt->execute();
  echo "Successfully added the new user " . $_POST['name'];
} catch (PDOException $e) {
  echo "DataBase Error: The user could not be added.<br>".$e->getMessage();
} catch (Exception $e) {
  echo "General Error: The user could not be added.<br>".$e->getMessage();
}
?>

PHPプラグインのすべての例外がExceptionネイティブPHP=クラスから継承しています。メモリが十分であれば5.0以降)ので、これは機能するはずです。

15
niconoe

PDO例外の質問-それらをキャッチする方法

原則として -

キャッチしないでください

たとえば、ここのコードはこのように書く必要があります

$stmt = $db->prepare("INSERT INTO tbl_user (id, name, password, question, answer) VALUES (NULL, :name, :password, :question, :answer)");
$stmt->bindValue(":name", $_POST['name']);
$stmt->bindValue(":password", $_POST['password']);
$stmt->bindValue(":question", $_POST['question']);
$stmt->bindValue(":answer", $_POST['answer']);
$stmt->execute();
echo "Successfully added the new user " . $_POST['name'];

試行またはキャッチの呼び出しなし。 ここで例外を処理するための特定のシナリオがないため(単純なエコーは処理シナリオとしてほとんどカウントされません)。

代わりに、アプリケーション全体のエラーハンドラーにバブルアップします(用語PHPには既に組み込みのものがあるため、恐れることはありません)。

ただし、私が希望するエラー(MySQLの「Duplicate Entry」、「Null Value」などのエラー)をキャッチするのに問題があります。

特定のシナリオがある場合にのみ、try-catch演算子を使用する必要がありますが、エラーが発生したかどうかを常に確認する必要があります得たのはあなたが期待したものです。それ以外の場合は、例外を再スローする必要があります。

try {
    $pdo->prepare("INSERT INTO users VALUES (NULL,?,?,?,?)")->execute($data);
} catch (PDOException $e) {
    if ($e->getCode() == 1062) {
        // Take some action if there is a key constraint violation, i.e. duplicate name
    } else {
        throw $e;
    }
}

そしてもちろん(この質問では非常に深刻な問題であることが判明したため)、PDOを例外モードで設定する必要があります。

$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

接続直後。

10