PHPを使用してデータベースを使用するには、次のスクリプトを使用しています。
_try{
$db = new PDO('mysql:Host='.$Host.';port='.$port.';dbname='.$db, $user, $pass, $options);
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}
_
ここで、このデータベースハンドルを使用して、このコードを使用してリクエストを実行します。
_try{
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(array(
'...' => $...,
'...' => $...
));
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}
_
ここに問題があります:
$GLOBALS['errors'][]
_配列があり、その後もスクリプトは実行されていますが、通知:未定義の変数:32行目のC:\ xampp\htdocs [...]\test.phpのdb
致命的なエラー:C:\ xampp\htdocs [...]\test.phpの32行目の非オブジェクトでのメンバー関数prepare()の呼び出し
注:32行目は$query = $db->prepare(...)
命令です。
つまり、スクリプトがクラッシュし、try/catchは役に立たないようです。この2回目のtry/catchが機能しない理由とその解決方法を知っていますか?
助けてくれてありがとう!
編集:本当に良い返信がいくつかあります。私が検証したいのは、私がやりたかったこととは厳密には一致しませんが、おそらくこれが最善のアプローチです。
try
/catch
ブロックは、スローされた例外に対してのみ機能します(_throw Exception
_またはException
のサブクラスを呼び出す必要があります)。 try
/catch
を使用して致命的なエラーをキャッチすることはできません。
DB接続を確立できない場合、おそらくページで意味のあることをDBが行う必要があるので、致命的だと考えます。
PDO
は、接続を確立できない場合に例外をスローします。あなたの特定の問題は、それを使ってメソッドを呼び出そうとしたときに_$db
_が定義されていないため、致命的なnullポインタ(一種)を取得することです。他の人が示唆しているようにif ($db == null)
フープをジャンプするのではなく、コードを修正して、_$db
_が必要なときに常に定義されるか、またはDB接続は、それを使用するコードで使用できます。
致命的なエラーを「キャッチ」したい場合は、_set_error_handler
_を使用しますが、これでも致命的なエラーでスクリプトの実行が停止します。
PHP7では、 致命的なエラーの試行を使用できるようになりました 簡単な作業で
try {
do some thing evil
} catch (Error $e) {
echo 'Now you can catch me!';
}
しかし、通常、catch Errorの使用は避ける必要があります。これは、プログラマーの責任に属するコードを見逃すことになるためです:-)
なぜtry ... catch
これを宣言するためのステートメント。これを交換してください:
try{
$db = new PDO('mysql:Host='.$Host.';port='.$port.';dbname='.$db, $user, $pass, $options);
}
と:
$db = new PDO('mysql:Host='.$Host.';port='.$port.';dbname='.$db, $user, $pass, $options) or die("Cannot Create PDO!");
またはあなたのやり方で:
$db = new PDO('mysql:Host='.$Host.';port='.$port.';dbname='.$db, $user, $pass, $options) or ($GLOBALS['errors'][] = "Cannot Create PDO!");
次のifステートメントを追加してみてください。
if ($db) {
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(....);
}
else die('Connection lost');
データベース接続が失敗した場合、最初の_$db
_ブロックの_try .. catch
_はnullになります。そのため、後で$db->prepare(...)
のように、非オブジェクトのメンバーを使用できなくなります。これを使用する前に
_if ($db) {
// other try catch statement
}
_
これにより、dbインスタンスを操作できるようになります。
$db
が空の場合、テストについてすでに何が書かれているかは報告しません。 「クリーン」な解決策は、データベースへの接続が失敗した場合に人為的に例外を作成することであると追加するだけです。
if ($db == NULL) throw new Exception('Connection failed.');
次のようにtry - catch
に前の行を挿入します。
try{
// This line create an exception if $db is empty
if ($db == NULL) throw new Exception('Connection failed.');
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(array(
'...' => $...,
'...' => $...
));
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}
これが他の人の役に立つことを願っています!
try{
if(!is_null($db))
{
$query = $db->prepare("INSERT INTO users (...) VALUES (...);");
$query->execute(array(
'...' => $...,
'...' => $...
));
}
}
catch(Exception $e){
$GLOBALS['errors'][] = $e;
}