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_string and 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.