Good Code
The good version prepares SQL once, binds the email as data, selects explicit columns, and handles the no-row case.
Lesson 04
Use prepared statements with bound values instead of interpolating request data into SQL strings.
<?php declare(strict_types=1);
final class UserRepository
{
public function __construct(private PDO $pdo) {}
public function findActiveByEmail(string $email): ?array
{
$stmt = $this->pdo->prepare(
'SELECT id, email, name FROM users WHERE email = :email AND active = 1'
);
$stmt->execute(['email' => $email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
return $user === false ? null : $user;
}
}<?php
$email = $_GET['email'];
$sql = "SELECT * FROM users WHERE email = '$email' AND active = 1";
$user = $pdo->query($sql)->fetch();The good version prepares SQL once, binds the email as data, selects explicit columns, and handles the no-row case.
The bad version interpolates a request value into SQL and selects every column. A reviewer cannot trust the query boundary or the response shape.