SQL injection defense
| How injection reads | |
| Prepare everything | |
| LIKE wildcards safely | |
| LIMIT with ints |
How injection reads
Injection happens when user input is glued into SQL text and the database reads part of that input as code. A quote in a name can then change the shape of the query.
The defense is structural and never relies on blocking bad words. Keep data and SQL text apart so input can only ever be a value.
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = :email"); $stmt->execute([":email" => $email]); echo $stmt->rowCount();
Prepare everything
Prepared statements send the SQL shape first and the values separately. The database compiles the query before it ever sees user data.
Use named placeholders for every value that comes from outside. Never build SQL by joining input with dots.
$stmt = $pdo->prepare("INSERT INTO posts (title, body) VALUES (:title, :body)"); $stmt->execute([":title" => $title, ":body" => $body]); echo $pdo->lastInsertId();
LIKE wildcards safely
Search boxes often need partial matches with percent and underscore wildcards. Build the pattern in PHP and send it as one bound value.
The placeholder still carries the whole pattern. User text inside it can never escape into SQL syntax.
$term = "%" . $q . "%"; $stmt = $pdo->prepare("SELECT id FROM posts WHERE title LIKE :term"); $stmt->execute([":term" => $term]); echo $stmt->rowCount();
LIMIT with ints
Limits and offsets cannot always be bound as placeholders, so force them to integers in PHP. Casting drops everything except digits and sign.
Clamp the result to a sane range before it reaches SQL. The query then contains only digits built by your own code.
$limit = max(1, (int)$n); $sql = sprintf("SELECT id FROM posts LIMIT %d", $limit); $stmt = $pdo->query($sql); echo $limit;
Next: Send email
Article author: Arthur Isaev