Самоучитель: динамические веб-приложения
Глава 9 из 18IV. Данные и MySQL105 минут

Глава 9. PDO, репозитории и транзакционные сценарии

PDO отвечает за протокол базы, репозиторий — за сохранение модели, а транзакционная граница принадлежит целому прикладному сценарию.

После главы вы сможете
  • настроить PDO
  • разместить SQL у адаптера
  • провести атомарный сценарий

Безопасное соединение

<?php
function openApplicationDatabase(
    string $dataSource,
    string $login,
    string $secret,
): PDO {
    $driverOptions = [
        PDO::ATTR_EMULATE_PREPARES => false,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    ];

    return new PDO($dataSource, $login, $secret, $driverOptions);
}

Значения отдельно от SQL

prepare() и execute() отделяют структуру запроса от значений. Placeholder не является функцией экранирования после конкатенации: полный SQL-шаблон создаётся до передачи данных. Для LIKE самостоятельно решите, считаются ли % и _ пользовательскими символами или шаблоном, и экранируйте согласно этому контракту.

Тип параметра имеет значение для LIMIT, булевых флагов и некоторых планов. bindValue позволяет указать PDO::PARAM_INT, но не используйте его механически для каждого значения.

Репозиторий переводит модели

Интерфейс TaskRepository говорит save, get и findByProject, а PDO-реализация знает таблицы и SQL. Mapper превращает строку результата в объект, не вызывая предметный конструктор в неверном состоянии. Контроллер не получает PDOStatement и не выбирает FETCH-режим.

Не создавайте универсальный repository с десятками параметров и произвольным массивом where. Предметные методы лучше показывают намерение и позволяют оптимизировать конкретный запрос.

Транзакция вокруг сценария

Атомарное изменениеЕсли любой шаг завершается ошибкой, rollback возвращает базу к состоянию до сценария.BEGINграницаUPDATEзадачаINSERTсобытиеCOMMITединый факт
Если любой шаг завершается ошибкой, rollback возвращает базу к состоянию до сценария.

Конкуренция существует и локально

Два запроса способны прочитать одну версию и перезаписать изменения друг друга. Optimistic locking добавляет version в условие UPDATE и проверяет число изменённых строк. Для короткого критического решения SELECT ... FOR UPDATE блокирует выбранные записи внутри транзакции, но требует стабильного порядка захвата.

Не удерживайте транзакцию, пока вызываете удалённый API или ждёте пользователя. Сначала завершите локальное состояние, а внешнее действие оформите через очередь или outbox, если нужна надёжная доставка.

Отказ и повтор

Deadlock и потеря соединения требуют отдельной политики. Автоматически повторяйте только идемпотентный сценарий либо весь transaction callback с ограниченным числом попыток. Повтор одного последнего INSERT после неопределённого исхода способен создать дубль.

Уникальный ключ и idempotency key переводят повтор из догадки в проверяемый контракт.

Практика главы

Реализуйте сценарий завершения задачи: обновить статус с проверкой version и добавить событие истории в одной транзакции. Разведите not found, forbidden и conflict.

Локальный прогресс

Закрепите материал

Отметка, заметка, чек-лист и ответы остаются в localStorage этого браузера и не отправляются в аналитику.

Перелинковка со справочником

Проверка актуальности

  • dev.mysql.comhttps://dev.mysql.com/doc/refman/8.4/en/Первичный источник для актуализации фактов. Адрес приведён как текст и не является активной ссылкой.

Текст и схемы созданы для этого самоучителя без воспроизведения страниц, иллюстраций и листингов приложенной книги. Проверено: .

Данные этого сервиса

Настройки cookie и локальных данных

Аналитика

Текущий статус: не выбран. До согласия обе аналитические системы не загружаются.

Локальные данные

Удаление затрагивает только ключи PHP-сервиса в этом браузере и требует подтверждения.

Политики

Политика конфиденциальности · Политика использования файлов cookie