mysqli_stmt::prepare是mysqli擴展中用於預處理SQL 語句的方法。與直接使用SQL 查詢字符串相比,預處理語句可以減少SQL 注入的風險。這是因為在執行SQL 時,用戶輸入的內容並不會直接拼接到查詢字符串中,而是作為綁定參數進行傳遞。
<span><span><span class="hljs-variable">$conn</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">mysqli</span></span><span>(</span><span><span class="hljs-variable">$host</span></span><span>, </span><span><span class="hljs-variable">$user</span></span><span>, </span><span><span class="hljs-variable">$password</span></span><span>, </span><span><span class="hljs-variable">$database</span></span><span>);
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$conn</span></span><span>->connect_error) {
</span><span><span class="hljs-keyword">die</span></span><span>(</span><span><span class="hljs-string">"Connection failed: "</span></span><span> . </span><span><span class="hljs-variable">$conn</span></span><span>->connect_error);
}
</span><span><span class="hljs-variable">$stmt</span></span><span> = </span><span><span class="hljs-variable">$conn</span></span><span>-></span><span><span class="hljs-title function_ invoke__">prepare</span></span><span>(</span><span><span class="hljs-string">"SELECT * FROM users WHERE username = ? AND password = ?"</span></span><span>);
</span></span>
在上述代碼中,SQL 查詢包含兩個問號( ? ),它們是佔位符,用來接受後續綁定的參數。
在預處理語句中,使用bind_param()方法來將用戶輸入的值綁定到佔位符上。此時,綁定的參數值將不會直接插入到SQL 語句中,而是通過預處理語句傳遞。 bind_param()方法需要兩個參數:數據類型的說明符和要綁定的變量。
常見的數據類型說明符有:
i :整數(int)
d :雙精度浮動點數(double)
s :字符串(string)
b :BLOB(binary data)
<span><span><span class="hljs-variable">$username</span></span><span> = </span><span><span class="hljs-string">'john_doe'</span></span><span>;
</span><span><span class="hljs-variable">$password</span></span><span> = </span><span><span class="hljs-string">'password123'</span></span><span>;
</span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">bind_param</span></span><span>(</span><span><span class="hljs-string">'ss'</span></span><span>, </span><span><span class="hljs-variable">$username</span></span><span>, </span><span><span class="hljs-variable">$password</span></span><span>);
</span></span>
在這個例子中, 'ss'表示綁定的兩個參數都是字符串類型。參數$username和$password將被安全地綁定到SQL 查詢中的佔位符。
在參數綁定完成之後,調用execute()方法來執行預處理語句。如果綁定的參數類型正確,執行語句將正常運行。
<span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">execute</span></span><span>();
</span></span>
execute()方法返回一個布爾值,表示語句是否執行成功。如果需要獲取查詢結果,可以使用get_result()方法(針對SELECT查詢)來獲取執行結果。
對於SELECT語句,執行完預處理語句後,通常需要獲取查詢的結果。使用get_result()方法可以將查詢結果轉換為一個mysqli_result對象,從中可以獲取數據。
<span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">get_result</span></span><span>();
</span><span><span class="hljs-keyword">while</span></span><span> (</span><span><span class="hljs-variable">$row</span></span><span> = </span><span><span class="hljs-variable">$result</span></span><span>-></span><span><span class="hljs-title function_ invoke__">fetch_assoc</span></span><span>()) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$row</span></span><span>[</span><span><span class="hljs-string">'username'</span></span><span>] . </span><span><span class="hljs-string">' - '</span></span><span> . </span><span><span class="hljs-variable">$row</span></span><span>[</span><span><span class="hljs-string">'email'</span></span><span>] . </span><span><span class="hljs-string">'<br>'</span></span><span>;
}
</span></span>
在這個例子中,查詢結果按行提取,並輸出用戶名和電子郵件。
雖然預處理語句能夠防止SQL 注入,但在實際開發中,仍然可能遇到各種錯誤。為了有效調試,我們可以使用error方法來獲取相關的錯誤信息。
<span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$stmt</span></span><span> === </span><span><span class="hljs-literal">false</span></span><span>) {
</span><span><span class="hljs-keyword">die</span></span><span>(</span><span><span class="hljs-string">'Error preparing statement: '</span></span><span> . </span><span><span class="hljs-variable">$conn</span></span><span>->error);
}
</span><span><span class="hljs-keyword">if</span></span><span> (!</span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">execute</span></span><span>()) {
</span><span><span class="hljs-keyword">die</span></span><span>(</span><span><span class="hljs-string">'Execute error: '</span></span><span> . </span><span><span class="hljs-variable">$stmt</span></span><span>->error);
}
</span></span>
這裡使用了conn->error和stmt->error來捕捉數據庫連接和執行語句的錯誤信息。這能夠幫助我們及時發現並解決問題。
使用完預處理語句後,我們需要調用close()方法來關閉語句和數據庫連接,以釋放資源。
<span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">close</span></span><span>();
</span><span><span class="hljs-variable">$conn</span></span><span>-></span><span><span class="hljs-title function_ invoke__">close</span></span><span>();
</span></span>
這不僅是一個良好的編程習慣,而且能有效地避免資源洩露。
相關標籤:
mysqli_stmt