Looking for a structured path? Browse all PHP lessons.

Maintained by
Learning Platform content team
Reviewed by
Learning Platform source and executable-example contract

PHP PDO prepared statements: safe queries by default

Prepared statements keep untrusted values separate from SQL syntax. That prevents an input such as ' OR 1=1 -- from changing the meaning of a query.

Unsafe string interpolation

<?php
$email = $_POST['email'] ?? '';
$sql = "SELECT id, email FROM users WHERE email = '$email'";

Quoting the value yourself is not a defense. The input can contain quote characters and SQL tokens.

Prepare, bind, execute

<?php
$pdo = new PDO('sqlite::memory:', null, null, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$pdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)');
$pdo->exec("INSERT INTO users (email) VALUES ('ada@example.test')");

$statement = $pdo->prepare(
    'SELECT id, email FROM users WHERE email = :email'
);
$statement->execute(['email' => 'ada@example.test']);
$user = $statement->fetch(PDO::FETCH_ASSOC);

echo $user['email'];

Expected output:

ada@example.test

Use positional ? or named :email placeholders consistently. Binding an integer with PDO::PARAM_INT is useful when the driver would otherwise infer it as a string.

Identifiers are different

Placeholders represent data values, not table names, column names, or ASC/DESC. For dynamic ordering, map a small public option to an allowlisted SQL fragment:

<?php
$columns = ['newest' => 'created_at DESC', 'name' => 'name ASC'];
$order = $columns[$_GET['order'] ?? 'newest'] ?? $columns['newest'];
$sql = "SELECT id, name FROM users ORDER BY $order";
echo $sql;

Failure modes

Do not log DSNs, passwords, full exception traces, or query values in a public response. Return a fixed error to the client and keep sanitized diagnostics in protected logs. Prepared statements also do not replace authorization: a safe query can still expose another user's row if its access rule is wrong.

Practice with Working With Databases, review Auth and Security, and use the PHP playground for syntax-only examples.

Official references