Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Паттерн DAO PHP PDO: Работа с базой данных

Работать напрямую с PDO в коде не очень удобно из-за большого количества низкоуровневых деталей и повторяющегося шаблонного кода. Кроме того, нам постоянно приходится преобразовывать данные в одну и в другую сторону.

Чтобы решить эту проблему, можно скрыть работу с базой за какой-то абстракцией. Один из вариантов такой изоляции называют DAO (Data Access Object).

Концепция DAO очень проста. Она сводится к созданию класса под каждую таблицу в базе данных. В классе реализуются методы, которые сохраняют, удаляют или ищут сущности в этой таблице. Когда речь идет о пользователях, наш класс DAO может выглядеть так:

class UserDAO {
    private \PDO $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }

    public function save(User $user): void
    {
        // Если пользователь новый, выполняем вставку
        // Иначе обновляем
        if (is_null($user->getId())) {
            $sql = "INSERT INTO users (username, phone) VALUES (?, ?)";
            $stmt = $this->pdo->prepare($sql);
            $username = $user->getUsername();
            $phone = $user->getPhone();
            $stmt->bindParam(1, $username);
            $stmt->bindParam(2, $phone);
            $stmt->execute();
            // Извлекаем идентификатор и добавляем в сохраненный объект
            $id = (int) $this->pdo->lastInsertId();
            $user->setId($id);
        } else {
            // Здесь код обновления существующей записи
        }
    }

    public function find(int $id): ?User
    {
        $sql = "SELECT * FROM users WHERE id = ?";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([$id]);
        $result = $stmt->fetch();
        if ($result) {
            $user = new User($result['username'], $result['phone']);
            $user->setId($id);
            return $user;
        }
        return null;
    }
}

Метод save() в этом классе не только сохраняет данные в базу, но и изменяет переданный объект, устанавливая внутри него идентификатор. Зачем это нужно? Код приложения работает с объектом, а не с базой напрямую. Соответственно, любые изменения в базе должны отражаться на объекте.

Если бы мы не установили идентификатор после сохранения пользователя, то не смогли бы:

  • Формировать ссылки — например, ссылку на редактирование пользователя
  • Сравнивать объекты друг с другом
  • Отличать существующих пользователей от новых, которых мы еще не сохранили в базу данных
  • Обеспечить работу кода так, чтобы полноценная версия save() проверяла наличие идентификатора и выполняла обновление данных, если его нет

Рассмотрим несколько примеров использования DAO:

// Устанавливаем соединение с базой данных
$conn = new PDO('sqlite::memory:');
$conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

$dao = new UserDAO($conn);
$user = new User('John', '555-1234');
$user->getId(); // null
$dao->save($user);
$user->getId(); // Здесь уже выводится какой-то id

$user2 = $dao->find($user->getId());
$user2->getId() == $user1->getId();

Самостоятельная работа

  • Выполните шаги из урока на своем компьютере
  • Перепишите код нашего приложения, используя DAO для таблицы пользователей. Чтобы это сделать, создайте класс User, который будет представлять пользователя
  • Добавьте в DAO еще один метод, который сможет удалять пользователей из таблицы по их идентификатору

Задача со звездочкой. База данных в памяти хороша для обучения и тестирования, но для рабочего приложения не годится. Заменим SQLite в памяти на полнофункциональную базу данных. Одна из наиболее распространенных СУБД — PostgreSQL. Для подключения к ней вам потребуется установить соответствующий драйвер и поднять локально PostgreSQL. Сделать это можно по нашей инструкции

  • Подключите созданный DAO к PostgreSQL. Попробуйте добавлять и удалять пользователей при помощи DAO, убедитесь, что все работает корректно

Дополнительные материалы

  1. Паттерн DAO

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
Занимайтесь созданием сайтов, веб-приложений, сервисов и их интеграцией с внутренними бизнес-системами на бекенд-языке PHP
10 месяцев
с нуля
Старт 28 ноября

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»