PDOでMySQLに接続して存在しないテーブルで500エラーが出て困った話

php・mySQLの技術的なお話です。
これまで、mysql_connectでSQLを呼び出していたのですが、SQLインクリジョン対策がめんどくさい。とにかくめんどくさい。
「この平成の世の中で、こんな原始人みたいなチマチマした作業をする必要があるのだろうか、、、?」
と、疑問が湧いてきたので調べてみました。
すると驚くべき事実。
mysql_connect:この拡張モジュールは PHP 5.5.0 で非推奨になり、PHP 7.0.0 で削除されました。
PHP: mysql_connect – Manual
マジか。
知らんかった。←不勉強すぎ
で、調べてみるとPDOを使ってmySQLに接続するとSQLインクリジョン対策が楽と分かったので早速お勉強。
mysql – PHP での SQL インジェクション対策はどのように行いますか? – スタック・オーバーフロー
まぁ、楽勝ですわ。
『余計なことせんと、言うた通りにしたらええねん。』
と、天の声が聞こえてきそうなほどさくさくコーディングが進みました。
〜本題はここから〜
エラー周りのデバッグをしていると、どういう訳が下記のSQL文をprepareに突っ込むと、サーバが500エラーを返してくる現象に気が付きました。
$sql = “SELECT * FROM 存在しないテーブル名”;
$sth = $pdo -> prepare($sql);
SQL文が間違っているからといって500エラーになるというのは、mysql_connectではなかった現象です。
「そもそも、テーブルが存在するかしないかは実行しないと分からんやないかいッ!!」
回避策を探そうにも、『テーブルが存在しなければprepareしない』という鶏が先か卵が先か的な問題で手詰まり感が半端ない。
「#php で #PDO を使って #mySQL に接続した時に、存在しないテーブル名を含んだ #SQL 文を #prepare に放り込んだ時に、500エラー出て止まるのはなんでか誰か教えろください。存在するテーブル名だと問題なく動くんですよ。」と、ツイッターに投げてみるも誰も返事なし。
「!! もしかして、そもそも、どこかでそういうエラーレベルをコントロールする設定があるのではないか?」
と、思いついてphp.iniをチェック。
ハズレ。
自分の書いたphpの1行目からよーく見てみる。
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
エラーモードって書いてあるね。
調べる。
PHP: エラーおよびエラー処理 – Manual
『デバッグ時に有用で、エラーが発生した時点で スクリプトの実行を停止させることによりコード内の問題点を 見つけやすくなります』
『// このテーブルが存在しないとして、このコードを実行すると E_WARNING レベルのエラーになります。例外にはなりません。』
ちゃんとマニュアルに書いてあるね。
デバッグ用の設定してたらそりゃぁ止まるわね。
// $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
こうしたら動きました。

カテゴリー: Web