← Back to PHP Course | Chapter 11: Database | Lesson 15 of 21

PHP MySQL Prepared Statements

user input को सीधे एक string में glue करके SQL query बनाना web applications के hack होने का सबसे common तरीका है -- एक technique जिसे SQL injection कहते हैं। Prepared statements इसे root पर fix करते हैं: SQL structure पहले database को भेजा जाता है, actual values से बिल्कुल अलग, ताकि user input कभी SQL code की तरह misinterpret न हो सके।
Syntax
php
$stmt = mysqli_prepare($conn, "SELECT * FROM table_name WHERE column = ?");
mysqli_stmt_bind_param($stmt, "s", $value);   // s = string, i = integer
mysqli_stmt_execute($stmt);

Prepared Statements क्यों Exist करते हैं

किसी variable को query string में directly concatenate करके SQL बनाना, जैसे "SELECT * FROM users WHERE name = '$name'", एक attacker को '; DROP TABLE users; -- जैसी एक value supply करने देता है जो query का actual meaning बदल देती है।

Prepared statements SQL template और values को दो पूरी तरह अलग चीज़ों की तरह भेजकर इसे रोकते हैं।

उदाहरण: Why Prepared Statements Exist

php
<?php
$name = "Robert'); DROP TABLE users; --";
// Never do: "SELECT * FROM users WHERE name = '$name'"
echo "The SQL template and the value are sent separately instead";
?>

Placeholders के साथ एक Statement Prepare करना

mysqli_prepare($conn, $sql) actual values की जगह एक या ज़्यादा ? placeholders वाला एक SQL statement compile करता है, एक statement object return करते हुए जिसे आप real values attach करके फिर execute करेंगे -- placeholders exactly बताते हैं कि values कहाँ जाएँगी बिना अभी यह specify किए कि वे क्या हैं।

उदाहरण: Preparing a Statement with Placeholders

php
<?php
$db = new SQLite3(':memory:');
$db->exec("CREATE TABLE users (name TEXT)");
$stmt = $db->prepare("INSERT INTO users (name) VALUES (?)"); // mysqli_prepare($conn, $sql)
echo "Statement compiled with a placeholder";
?>

bind_param से Values Bind करना

mysqli_stmt_bind_param($stmt, $types, ...$values) actual values को एक prepared statement के placeholders से order में attach करता है -- $types string MySQL को हर value की kind बताती है: integer के लिए "i", double/float के लिए "d", string के लिए "s", और binary blob data के लिए "b"।

उदाहरण: Binding Values with bind_param

php
<?php
$db = new SQLite3(':memory:');
$db->exec("CREATE TABLE users (id INTEGER, name TEXT)");
$stmt = $db->prepare("INSERT INTO users (id, name) VALUES (?, ?)");
$stmt->bindValue(1, 1, SQLITE3_INTEGER); // like "i" in mysqli's bind_param
$stmt->bindValue(2, "Alice", SQLITE3_TEXT); // like "s"
$stmt->execute();
echo "Values bound by type";
?>

Execute करना और Results Retrieve करना

mysqli_stmt_execute($stmt) prepared statement को इसकी bound values के साथ चलाता है, और mysqli_stmt_get_result($stmt) statement के result को एक regular result set में convert करता है जिस पर आप plain query के लिए इस्तेमाल किए गए same fetch functions से loop चला सकते हैं, जैसे mysqli_fetch_assoc()।

उदाहरण: Executing and Retrieving Results

php
<?php
// Create a new `SQLite3` instance with ':memory:', stored in `$db`
$db = new SQLite3(':memory:');
$db->exec("CREATE TABLE users (name TEXT)");
$db->exec("INSERT INTO users (name) VALUES ('Alice')");
// Declare `$stmt`, set to `$db->prepare("SELECT * FROM users WHERE name = ?")`
$stmt = $db->prepare("SELECT * FROM users WHERE name = ?");
$stmt->bindValue(1, "Alice", SQLITE3_TEXT);
// Declare `$result`, set to `$stmt->execute()`
$result = $stmt->execute();
// Print a human-readable dump of `$result->fetchArray(SQLITE3_ASSOC)`
print_r($result->fetchArray(SQLITE3_ASSOC));
?>

एक Prepared Statement को Reuse करना

एक single prepared statement को हर बार re-prepare किए बिना अलग-अलग bound values के साथ कई बार execute किया जा सकता है -- हर नए set of values के लिए बस bind_param (या rebind) call करें और फिर execute करें, जो प्रति call एक fresh statement prepare करने से safer और तेज़ दोनों है।

उदाहरण: Reusing a Prepared Statement

php
<?php
$db = new SQLite3(':memory:');
$db->exec("CREATE TABLE users (name TEXT)");
$stmt = $db->prepare("INSERT INTO users (name) VALUES (?)");
foreach (["Alice", "Bob", "Carol"] as $name) {
    $stmt->bindValue(1, $name, SQLITE3_TEXT);
    $stmt->execute(); // same statement, new values each time
}
echo "3 rows inserted with one prepared statement";
?>
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. यह सोचकर किसी query के लिए prepared statements skip कर देना कि input 'safe लगता है', जबकि किसी user से आई, indirectly भी, कोई value untrusted मानी जानी चाहिए।
  2. bind_param call करते समय सही type string (s, i, d, b) specify करना भूल जाना, values को गलत तरीके से interpret होने का कारण बनाते हुए।
  3. उसी query में manually escaped, concatenated SQL को prepared statement placeholders के साथ mix करना, prepared statements द्वारा दी जाने वाली safety को defeat करते हुए।
चैप्टर सारांश
  • mysqli_prepare($conn, $sql) एक SQL statement compile करता है जिसमें values जाने वाली जगह ? placeholders होते हैं, कोई actual data attach होने से पहले।
  • mysqli_stmt_bind_param($stmt, $types, ...$values) placeholders से real values attach करता है, हर value की kind बताने वाली एक type string के साथ।
  • Database engine SQL structure और bound values को strictly अलग रखता है, bound values के through SQL injection को structurally असंभव बनाते हुए।

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.