當前位置: 首頁> 最新文章列表> 使用stmt_init 後忘記調用prepare() 會發生什麼?

使用stmt_init 後忘記調用prepare() 會發生什麼?

M66 2025-05-29

在使用PHP 的mysqli擴展進行數據庫操作時,預處理語句是一種常見且安全的做法。開發者通常會使用mysqli::stmt_init()來初始化一個語句對象,然後通過prepare()方法準備SQL 語句。然而,如果在調用stmt_init()後忘記執行prepare() ,將會導致一些隱性問題,本文將對此進行分析和舉例說明。

一、 stmt_init()prepare()的基本用法

通常,我們的代碼結構是這樣的:

 $mysqli = new mysqli("localhost", "user", "password", "database");
$stmt = $mysqli->stmt_init();
$stmt->prepare("SELECT * FROM users WHERE id = ?");

其中:

  • stmt_init()初始化一個mysqli_stmt對象;

  • prepare()準備一個SQL 語句,並與該對象綁定。

二、如果忘記調用prepare()會發生什麼?

如果你只調用了stmt_init()而沒有調用prepare() ,程序在後續使用該語句對象時將出現以下幾類問題:

1. 方法調用錯誤

在未調用prepare()的情況下直接調用bind_param()execute()等方法,會導致拋出警告甚至致命錯誤:

 $mysqli = new mysqli("localhost", "user", "password", "database");
$stmt = $mysqli->stmt_init();
// 忘記調用 prepare()

$stmt->bind_param("i", $userId); // 這裡將報錯
$stmt->execute();                // 這裡也將失敗

錯誤提示可能是:

 Fatal error: Uncaught Error: Call to a member function bind_param() on bool

或者:

 Warning: mysqli_stmt::bind_param(): invalid object or not initialized

2. 無法發現語法錯誤

如果你只是初始化了語句對象卻沒有prepare() ,那麼原本可以在prepare()階段發現的SQL 錯誤將被隱藏,直到執行時才可能導致不明確的錯誤。這會增加調試成本。

3. 安全風險

忘記使用prepare()意味著你可能直接拼接SQL 語句,這將繞過參數綁定的機制,從而增加SQL 注入風險。例如:

 // 錯誤示例(沒有 prepare)
$userId = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $userId";
$result = $mysqli->query($query);

如果沒有prepare()和參數綁定,用戶輸入將直接嵌入SQL 中,攻擊者可以構造如下URL:

 https://m66.net/get_user.php?id=1 OR 1=1

將導致數據洩露。

三、正確的做法

始終配對使用stmt_init()prepare() ,如下所示:

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

$stmt = $mysqli->stmt_init();
if ($stmt->prepare("SELECT * FROM users WHERE id = ?")) {
    $stmt->bind_param("i", $userId);
    $stmt->execute();
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        echo $row['username'] . "<br>";
    }
    $stmt->close();
} else {
    echo "SQL prepare 錯誤: " . $mysqli->error;
}

四、總結

忘記調用prepare()會導致以下問題:

  • 調用其他語句方法時出現錯誤;

  • SQL 錯誤無法提前被捕捉;

  • 增加SQL 注入等安全風險。

建議在使用stmt_init()後總是緊接著調用prepare() ,並對其返回值進行判斷,確保程序的穩定性與安全性。