PHP 7: Maintaining and Upgrading Legacy Apps · Security Hardening for PHP 7 Apps
Migrating from mysql_* and String SQL to PDO
Remove injection-prone queries and dead extensions.
The mysql_* extension was removed in PHP 7.0; apps that 'upgraded' often switched to mysqli_* while keeping string-concatenated SQL. Migrate queries to PDO prepared statements (or mysqli prepared statements), starting with code that touches user input. Grep for mysqli_query, ->query( with variables, and . concatenation near SELECT/WHERE.
<?php
// Before (SQL injection)
$res = mysqli_query($conn, "SELECT * FROM users WHERE email = '" . $_POST['email'] . "'");
// After
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$_POST['email'] ?? '']);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
Common pitfalls
- Replacing concatenation with
mysqli_real_escape_stringand assuming it's always safe (it fails for unquoted numeric contexts and identifiers). - Migrating only SELECTs and leaving INSERT/UPDATE/DELETE vulnerable.
- Missing the connection charset, enabling encoding-based attacks.
Key points
- Prioritize queries touching user input
- Prepared statements everywhere
- Set utf8mb4 charset on the connection
Further reading: PHP manual: choosing a MySQL API
Practice questions
Why isn't mysqli_real_escape_string a complete defense?
Answer
It only escapes string literals; it doesn't protect numeric contexts (WHERE id = $id without quotes) or identifiers, and depends on the connection charset being set correctly.
How do you find injection-prone queries in a big codebase?
Answer
Search for query functions with variables in the SQL string (mysqli_query, ->query("...$), concatenation near SQL keywords, and use static analysis/security scanners like Psalm taint analysis.
Open in the app to mark lessons complete, take notes and track your progress.