How do you prevent SQL injection in PHP, and what is the difference between PDO and MySQLi?
Prepared statements with bound parameters are the answer. The SQL structure is sent to the database separately from the values, so a value can never be interpreted as SQL.
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? AND status = ?');
$stmt->execute([$email, $status]);
$user = $stmt->fetch();Escaping functions such as mysqli_real_escape_string are a weaker fallback — they depend on the correct connection charset and are easy to apply inconsistently. Never build SQL with string concatenation or interpolation of user input.
PDO versus MySQLi:
- PDO supports twelve database drivers, so your data layer is portable. It has a consistent object API, named placeholders, and can throw exceptions on error.
- MySQLi is MySQL-only but exposes MySQL-specific features such as asynchronous queries.
PDO is the usual recommendation unless you need something MySQL-specific.
Note: Two configuration points matter. Set PDO::ATTR_ERRMODE to ERRMODE_EXCEPTION so failures are not silently ignored, and set PDO::ATTR_EMULATE_PREPARES to false so the database does the preparing rather than the driver — emulated prepares are not equivalent protection.





