PHP

Lesson 04

PDO prepared statements

Use prepared statements with bound values instead of interpolating request data into SQL strings.

Good Code

src/UserRepository.php
<?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;
    }
}

Bad Code

users.php
<?php

$email = $_GET['email'];
$sql = "SELECT * FROM users WHERE email = '$email' AND active = 1";
$user = $pdo->query($sql)->fetch();

Review Notes

What to review

Good Code

The good version prepares SQL once, binds the email as data, selects explicit columns, and handles the no-row case.

Bad Code

The bad version interpolates a request value into SQL and selects every column. A reviewer cannot trust the query boundary or the response shape.

Takeaways

  • SQL structure and SQL values should stay separate; PDO placeholders make that boundary reviewable.