Separate instructions from data
A prepared statement lets values be passed as parameters rather than concatenated into SQL. This reduces the risk of input changing the query structure. Parameters represent values; dynamic table or column names need an explicit allowlist.
Transactions and ownership
Use a transaction when several changes must commit together. Also enforce authorization: a parameterized query can still return someone else’s record if it does not restrict ownership. Query safety and authorization solve different problems.
Guided workplace application
A private-note query needs two decisions: separate values from SQL structure and restrict the resource to authorized scope. Use parameters for IDs and text; the authenticated user must come from server-validated context, not an arbitrary owner_id supplied in the request. To sort by title or created_at, map the received option to one of the fixed allowed columns. Do not expect ORDER BY:column to turn a parameter into an identifier. In IN, a comma-separated string does not become a value list either: build one placeholder per validated value and define empty-list behavior. Transactions group writes under engine guarantees but do not grant permission or automatically eliminate concurrency.
$stmt = $pdo->prepare(
"SELECT id, title FROM notes WHERE id =:id AND user_id =:user"
);
$stmt->execute(["id" => $noteId, "user" => $currentUserId])A user changes a note identifier in the URL. The application must look up the note within the authenticated account and refuse access to other accounts’ notes.
Common pitfalls
Binding column names as values; concatenating supplied lists; trusting client owner_id.
Related topics: Security at the web boundary · PDO transactions and partial failures
Parameterize values and verify the owner of every protected resource.
Reference: PHP manual: PDO prepared statements · PHP 8.5 reference; DR PHP 2026.2; new fixtures executed on PHP 8.3.17