[PHP] mysqliエラーを例外に変換してthrowする

2019-08-07PHPSQL, セキュリティ

mysqli には、 mysqli_sql_exception クラスが存在するが、そのままでは例外は発生しない。
エラーは例外として throw させて try ~ catch 文でキャッチさせる方法をメモ。


例外として throw させるには mysqli_report を設定する。

mysqli_report( MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT );
パラメータの種類
オプション名 説明
MYSQLI_REPORT_ERROR エラーを出す
MYSQLI_REPORT_STRICT エラーを mysqli_sql_exception に変換しスローする
MYSQLI_REPORT_INDEX クエリでインデックス未使用、または不適切な場合、警告を出す
MYSQLI_REPORT_ALL すべてのオプションを有効にする
MYSQLI_REPORT_OFF レポートをオフにする

サンプルコード
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

try {
	$result = $mysqli->query("SELECT * FROM hoge WHERE hogeprice > 10000");

} catch (mysqli_sql_exception $e) {	// Exception クラスでも catch できる
	echo 'mysqli_sql_exception<br>'.$e->getMessage();
	exit;
}
「 hoge 」というテーブルが存在しない場合の echo 表示

mysqli_sql_exception
Table ‘db.hoge’ doesn’t exist

SELECT の部分を SELECTA にして文法を間違った場合の echo 表示

mysqli_sql_exception
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘SELECTA * FROM hoge WHERE hogeprice > 10000’ at line 1

サンプルコードでは mysqli_sql_exception でキャッチしているが、 Exception クラスでもキャッチすることができた。

mysqli からのエラーメッセージは、悪意のあるデータを送られたり、 SQL インジェクションへのヒントになり得るため、デフォルトで画面に表示されないようになっているのだとか。よって、本番が不特定多数の誰でも見ることのできる環境であれば、エラーやキャッチした例外のメッセージは表示させない方が良い。

Posted by Agopeanuts