PHP / CHAPTER 11
Prepared statements and database boundaries
AdvancedSeparate SQL structure from data and preserve transaction semantics.
By the end of this chapter
- Bind values instead of concatenating SQL
- Keep identifier selection under an allowlist
- Use transactions for all-or-nothing work
The idea
A prepared statement separates SQL structure from parameter values. Bind user-provided values through placeholders instead of concatenating them into SQL text. This protects the statement’s structure and makes quoting responsibilities explicit. Placeholders represent values, not arbitrary table names, column names, or keywords, so dynamic identifiers require a controlled selection from known allowed choices.
A transaction groups related changes under one commit decision. Validate inputs first, begin the transaction at the appropriate boundary, and roll back when one required step fails. Parameter binding and transactions solve different problems: safe values do not automatically make several updates atomic. Preserve useful errors for the caller, and never report success merely because the first statement ran when later required work failed.
<?php
// Given a PDO connection $db with a tasks table:
$sql="SELECT id FROM tasks WHERE status = :status ORDER BY id";
$stmt=$db->prepare($sql);
$stmt->execute(["status"=>"open"]);
// fetchAll(PDO::FETCH_COLUMN) now obtains matching IDs.
echo "Query executed with a bound status\n";Query executed with a bound status
The example assumes a configured connection and table; the status remains data bound to a fixed query structure.
Try it yourself
Choose an ordering column from an allowlist, then bind the requested status as a value.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING