現在の位置: ホーム> 最新記事一覧> mysqli_stmt :: $エラー構文エラーの理由とソリューションをキャプチャできません

mysqli_stmt :: $エラー構文エラーの理由とソリューションをキャプチャできません

gitbox 2025-05-28

データベース操作にPHPのMySQLI拡張機能を使用する場合、準備されたステートメントを使用してセキュリティとパフォーマンスを向上させることがよくあります。同時に、開発者は、実行中のSQL構文エラーなどの可能なエラーを正確にキャプチャしたいことがよくあります。しかし、あなたはそのような紛らわしい問題に遭遇するかもしれません:

それで、何が起こっているのですか?この記事では、この問題の詳細な分析を実施し、実用的なソリューションを提供します。

1。問題が再び現れます

次のサンプルコードを参照してください。

 $mysqli = new mysqli("localhost", "user", "password", "testdb");

// 構文エラー:1つはありません FROM
$sql = "SELECT id name users WHERE id = ?";

$stmt = $mysqli->prepare($sql);

if (!$stmt) {
    echo "Prepare failed: " . $mysqli->error;  // それを行う正しい方法
} else {
    $stmt->bind_param("i", $id);
    $id = 1;
    $stmt->execute();

    if ($stmt->error) {
        echo "Execute error: " . $stmt->error; // 不会捕捉到構文エラー
    }

    $stmt->close();
}
$mysqli->close();

出力結果:

 Prepare failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version...

ご覧のとおり、 SQL構文エラーは$ stmt->エラーをまったく入力しませんが、 prepare()段階で$ mysqli->エラーでキャッチされます。

2。原因分析

PHPのMysqliMysqli_stmtの間の分業を理解する必要があります。

  • mysqli :: prepare()は、データベース接続オブジェクトによって呼び出されるメソッドです。 SQLに構文エラーがある場合、 STMTオブジェクトはまったく生成されないため、 $ STMTです。

  • mysqli_stmt :: $エラーは、ステートメントが正常に準備され、ランタイムエラーが発生した後にのみ値があります(バインディング変数タイプは、実行中に一致しません。外部キーの制約が失敗するなど)。

  • したがって、 SQL構文エラーは、STMTオブジェクトを作成しないため、 $ STMT->エラーでキャッチすることはなく、キャッチできません

言い換えると:

SQL構文エラーはprepare()段階で発生し、 $ stmt-> execute()を待つのではなく、 $ mysqli-> error :: prepare()の返品値で審査する必要があります。

3.正しいエラー処理方法

上記のコードを書き換えて、より安全なエラー処理ロジックを採用します。

 $mysqli = new mysqli("localhost", "user", "password", "testdb");

$sql = "SELECT id, name FROM users WHERE id = ?";  // 正しい構文

$stmt = $mysqli->prepare($sql);

if (!$stmt) {
    // 检查構文エラー
    die("SQL prepare failed: " . $mysqli->error);
}

$stmt->bind_param("i", $id);
$id = 1;

if (!$stmt->execute()) {
    // ランタイムエラーを確認してください
    die("Execute failed: " . $stmt->error);
}

$result = $stmt->get_result();
$data = $result->fetch_assoc();

echo "User: " . $data['name'];

$stmt->close();
$mysqli->close();

4.見落とされやすい安全上の危険

AJAXインターフェイスを使用して、このようなアドレスにアクセスするなど、SQLパラメーターを送信している場合:

 https://gitbox.net/api/get_user.php?id=1

次に、ユーザーの入力をSQLにスプライスします(危険!):

 $id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id";  // 潜在的 SQL 注射リスク

この執筆方法は、スプライシング中にSQLを誤って書くのが簡単で、 prepare()は使用されず、エラーを見つけるのがより困難です。したがって、次の記述方法が推奨されます。

 $sql = "SELECT * FROM users WHERE id = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("i", $_GET['id']);

これにより、SQLインジェクションが回避されるだけでなく、エラーチェックが明確で集中化されます。

5。概要

  • SQL構文エラーはprepare()段階でのみ見つけることができ、 $ stmt->エラーでは取得できません。

  • prepare()の返品値を確認し、 $ mysqli->エラーを使用してエラーメッセージを出力してください。

  • 注入を防ぐために前処理ステートメントを使用することをお勧めします。エラーをデバッグしてキャッチする方が簡単です。

MySQLIMySQLI_STMTの間の責任の分割を理解することによってのみ、より堅牢で安全なデータベースインタラクションコードを記述できます。