Безопасное соединение
<?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. Предметные методы лучше показывают намерение и позволяют оптимизировать конкретный запрос.
Транзакция вокруг сценария
Конкуренция существует и локально
Два запроса способны прочитать одну версию и перезаписать изменения друг друга. 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/Первичный источник для актуализации фактов. Адрес приведён как текст и не является активной ссылкой.
Текст и схемы созданы для этого самоучителя без воспроизведения страниц, иллюстраций и листингов приложенной книги. Проверено: .