Query a database with PDO prepared statements
Connect with PDO in exception mode and bind parameters to prevent SQL injection.
- PHP
- GreenSnippets
- MIT
<?php
$pdo = new PDO(
'pgsql:host=localhost;dbname=app',
getenv('DB_USER'),
getenv('DB_PASSWORD'),
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]
);
$stmt = $pdo->prepare('SELECT id, email FROM users WHERE email = :email AND active = :active');
$stmt->execute(['email' => $_POST['email'] ?? '', 'active' => true]);
$user = $stmt->fetch(); // associative array, or false when not foundHow it works
Never concatenate user input into SQL. A prepared statement sends the query and the values separately, so input cannot change the query structure. Setting ERRMODE_EXCEPTION makes failures impossible to ignore, and disabling emulated prepares uses real server-side parameters.
Placeholders can bind values only, not table or column names. For dynamic identifiers, validate against an allow-list.
This snippet needs a database server, so it has not been executed in an automated test here.
This snippet has been reviewed but was not executed by an automated test. Test it in your own environment before relying on it.
Related snippets
- SQL
Top N rows per group
Get the latest or highest N rows for each category using ROW_NUMBER in a subquery.
- SQL
Soft delete with a partial unique index
Keep deleted rows but still enforce unique emails among active rows using a partial unique index.
- SQL
Walk a tree with a recursive CTE
Query an employee/manager or category hierarchy to any depth using WITH RECURSIVE.
- SQL
Pivot rows into columns with FILTER
Turn row values into columns (for example monthly totals) using conditional aggregates, without crosstab.

