PHP Prepared Statements
PHP prepared statements securing MySQL queries
When working with PHP and MySQL, security and performance are critical. Prepared statements help you write safer and more efficient SQL queries—especially when handling user input such as login forms, search queries, and form submissions.
In this tutorial, you’ll learn:
What prepared statements are
Why they are important
How to use prepared statements with mysqli
How to use prepared statements with PDO
Examples for SELECT, INSERT, UPDATE, and DELETE
Best practices for secure PHP MySQL code
A prepared statement is a feature used to execute the same SQL statement repeatedly with high efficiency and security.
It works in two steps:
Prepare – Send the SQL query structure (with placeholders) to the database.
Execute – Bind actual values to the placeholders and run the query.
Example structure:
SELECT * FROM users WHERE email = ? AND status = ?
The ? marks are placeholders for values that will be safely bound later.
Prepared statements separate SQL logic from data, preventing attackers from injecting malicious SQL via input fields.
No need to manually escape strings or concatenate values into SQL queries.
The database can reuse the prepared query structure when running similar statements multiple times.
mysqli
You can use prepared statements with mysqli in two styles:
Object-oriented
Procedural
We’ll use object-oriented style here.
<?php
$host = "localhost";
$user = "root";
$pass = "";
$dbname = "php_crud_demo";
$conn = new mysqli($host, $user, $pass, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
?>
<?php
include 'db_connect.php';
$name = "Shubham";
$email = "shubham@example.com";
$city = "Bhopal";
$stmt = $conn->prepare("INSERT INTO users (name, email, city) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $name, $email, $city); // sss = 3 strings
if ($stmt->execute()) {
echo "User inserted successfully";
} else {
echo "Error: " . $stmt->error;
}
$stmt->close();
$conn->close();
?>
bind_param() Type Definitions
s → string
i → integer
d → double
b → blob (binary)
Example: "sid" = string, integer, double.
<?php
include 'db_connect.php';
$email = "shubham@example.com";
$stmt = $conn->prepare("SELECT id, name, city FROM users WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "ID: " . $row['id'] . " - Name: " . $row['name'] . " - City: " . $row['city'] . "<br>";
}
} else {
echo "No user found.";
}
$stmt->close();
$conn->close();
?>
<?php
include 'db_connect.php';
$newCity = "Indore";
$id = 1;
$stmt = $conn->prepare("UPDATE users SET city = ? WHERE id = ?");
$stmt->bind_param("si", $newCity, $id);
if ($stmt->execute()) {
echo "User updated successfully";
} else {
echo "Error: " . $stmt->error;
}
$stmt->close();
$conn->close();
?>
<?php
include 'db_connect.php';
$id = 3;
$stmt = $conn->prepare("DELETE FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
if ($stmt->execute()) {
echo "User deleted successfully";
} else {
echo "Error: " . $stmt->error;
}
$stmt->close();
$conn->close();
?>
PDO (PHP Data Objects) is a database abstraction layer that supports multiple databases (MySQL, PostgreSQL, SQLite, etc.). It uses prepared statements by default.
<?php
$host = "localhost";
$db = "php_crud_demo";
$user = "root";
$pass = "";
$dsn = "mysql:host=$host;dbname=$db;charset=utf8";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
die("Connection failed: " . $e->getMessage());
}
?>
<?php
include 'pdo_connect.php';
$name = "Rahul";
$email = "rahul@example.com";
$city = "Delhi";
$sql = "INSERT INTO users (name, email, city) VALUES (:name, :email, :city)";
$stmt = $pdo->prepare($sql);
$stmt->execute([
':name' => $name,
':email' => $email,
':city' => $city
]);
echo "User inserted successfully";
?>
<?php
include 'pdo_connect.php';
$email = "rahul@example.com";
$sql = "SELECT id, name, city FROM users WHERE email = :email";
$stmt = $pdo->prepare($sql);
$stmt->execute([':email' => $email]);
$users = $stmt->fetchAll();
if ($users) {
foreach ($users as $user) {
echo $user['id'] . ' - ' . $user['name'] . ' - ' . $user['city'] . '<br>';
}
} else {
echo "No user found.";
}
?>
Always use prepared statements for user input in SQL (forms, search boxes, login, etc.).
Avoid building SQL strings by concatenating variables directly.
Use appropriate data types (i, s, etc.) in bind_param().
Validate and sanitize inputs even when using prepared statements.
Catch and log database errors instead of showing them to users.
Prepared statements in PHP (using mysqli or PDO) are essential for:
Securing your application from SQL injection
Writing clean and maintainable database code
Optimizing repeated query execution
As you build login systems, search features, admin panels, and APIs, make prepared statements your default way of working with SQL.