2012-06-19 18 views
16

私はPDOを使用して、データベースのWebサイトインターフェイスを書き換えています。私はmysqlの拡張機能を使用していましたが、エラー処理に悩まされたことは一度もありませんでした。PDO例外質問 - キャッチする方法

今、私はこれを正しく実行したいと思います。しかし、私はどのようにしたいと思いますか(MySQLの "重複エントリ"、 "Null値"などのエラー)をキャッチする問題を抱えています。私のステートメントのどれが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ブロックにする必要がない、次のコードを実行するとき、それはエラーをキャッチしていない理由を私は理解できませんか? executeブロックをtryブロックに置くことはできますか?エラーDuplicate value "John" in key "name"をキャッチする必要がありますが、代わりに成功メッセージが表示されます。 (2人の "John"ユーザーを追加しようとすると)。私はPHPMyAdminをチェックした。索引は一意であり、このコードを使用しないで、予期したとおりにエラーをスローします。

+3

'$ db'の' PDO :: ATTR_ERRMODE'を 'PDO :: ERRMODE_EXCEPTION'に設定する必要がありますので、エラー時に例外がスローされます。 – FtDRbwLXw6

+0

ドキュメントやソースコードをチェックし、どの関数が 'PDOException'を投げるのか調べるべきです。それで、あなたはtryブロックに入れるコードの部分を知っているでしょう:) –

+0

'ATTR_ERRMODE'を固定して愚かな気持ちになりました。どのくらいの文をtryブロックに入れるべきですか?コードが再利用されるかもしれません(bindValue()のほんの少しのステートメントが変更された後にexecuteされます)。 tryブロックに文全体を入れることに利点がありますか、またはexecute()だけが必要ですか? – StuckAtWork

答えて

10

ドキュメントを参照してください。しかし、あなたが何かを見つけるいけない場合、あなたは別の漁獲量を追加することができます:

<?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クラスからPHPのプラグインheritsのすべての例外ので、働かなければなりません。 (私の記憶が良ければ5.0から)。

+1

私は見ましたPDOがデフォルトで例外を投げたと間違って判断したと思います。 @drrcknlsnが最初のコメントで言ったようにする必要があることがわかります。どちらのバージョン( '例外NOR PDOException')も変更されるまでエラーを投げていませんでした。しかし、これは悪い考えではありません(他のエラーが発生する可能性があります)。 – StuckAtWork

+1

@StuckAtWork :: bindValueまたは:: bindParamは、オブジェクトまたは配列を送信すると失敗する可能性があります。 $ _POSTを直接使用しても、ここで配列を送信するときにXSSの注入を妨げることはありません。 (PS:未知の理由で、私はあなたの尋問にコメントをつけることができないので、上記のコメントをここに書いていますか?_?)申し訳ありません。 – niconoe

+0

$ _POSTを正しくエンコードするにはどうすればよいですか? – StuckAtWork

10

PDO例外質問 -

DO NOT catch them - 原則として、それらに

をキャッチする方法。

たとえば、ここにあなたのコードは、任意の試みやキャッチ呼び出しなしでこのよう

$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の "重複エントリ"、 "ヌル値"などのエラー)のエラーをキャッチしています。あなたは特定のシナリオを持っている場合

のみの場合には、あなたはの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); 

接続直後です。

+0

私は、この特定の例で 'getCode()'が '$ e-> errorInfo [0]'で返される '23000'をすべてのドライバ(テスト済みのMySQLとMS SQL Server)でうまくいけばいいと思います。 '1062'コードはMySQLの' $ e-> errorInfo [1] 'に埋め込まれ、MS SQL Serverは' $ e-> errorInfo [1] 'の' 2627' –

関連する問題