Задать вопрос
@IvanIF

Нужно ли проверять каждое обращение к БД на php?

Есть например AJAX-скрипт подписки пользователя на пользователя. В этом скрипте нужно:

1)Проверить есть ли у пользователя действующая подписка
2)Подписать пользователя
3)Увеличить счётчик подписчиков у объекта подписки
4)Увеличить счётчик подписок у пользователя
5)Отправить объекту подписки уведомление

Это как минимум 5 sql запросов. Надо ли проверять возможные ошибки после каждого обращения к БД? Или достаточно проверить ошибки у 1-го запроса и если их нет, то продолжить?
  • Вопрос задан
  • 250 просмотров
Подписаться 2 Простой Комментировать
Решения вопроса 1
FanatPHP
@FanatPHP
Чебуратор тега РНР
Очень хороший вопрос.
Он вызван одной из родовых болезней РНР, в котором по какой-то причине именно операции с базой данных традиционно проверяются на каждый чих. При этом на все остальные операции почему-то никто не обращает внимания.

Большинство складывателей букв на РНР об этом не задумываются вообще, и очень хорошо что тебе пришел в голову этот вопрос. А ответ на него очень простой:

Проверять обращения к БД не нужно вообще

(за исключением нескольких специальных случаев, когда есть определенный сецнарий обработки ошибки)
Если же такого сценария нет, то никак проверять не нужно. Просто потому, что обращения к БД ничем не отличаются от любого другого кода.
И поскольку ты не проверяешь каждый include или там оператор деления, то не нужно и проверять запросы к БД. Их надо оставить в покое. И первый, и каждый по отдельности, и все 5 разом.

А вот что нужно сделать - это договориться с РНР, чтобы он сам сообщал тебе об ошибках в запросах. Для mysqli надо написать перед коннектом
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

Для ПДО при соединении выставить в настройках соединения

PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION

Всё. Больше ничего для обращений к БД делать не надо.

А вот обработчик ошибок, общий для всего кода, а не только для работы с БД, настроить желательно.
Чтобы AJAX-скрипт подписки получал соответствующий НТТР статус при любой ошибке, которая может возникнуть на сервере.
Ну и разумеется AJAX-скрипт подписки должен проверять НТТР статус, и обрабатывать ответ только если статус= 200
Пример обработчика можно посмотреть здесь

Если же надо убедиться, что все пять запросов выполнились без ошибок, то для таких целей служат транзакции.
Суть транзакции именно в том, что либо выполнияются либо все запросы, либо ни одного.
Если заключить все 5* запросов в транзакцию, то если при выполнении одного из них произойдет ошибка, то изменения, сделанные остальными, автоматически откатятся!

*На самом деле в транзакцию имеет смысл заключать только запросы, изменяющие данные. То есть все, кроме первого.

Соотсветственно, если ПДО настроен на выброс исключений, то при ошибке запроса
- пдо выбросит ислючение
- которое будет поймано обработчиком ошибок
- который выведет код ошибки и завершит работу РНР скрипта
- при завершении скрипта РНР закроет соединение с БД
- БД при закрытии соединения автоматически откатит незавершенную транзакцию

причем без обработчика ошибок будет всё то же самое, только клиенту уйдет код не 500 а 200

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

1. выставить для ПДО режим исключений
2. перед первым запросом написать $pdo->begin();
3. после последнего запроса написать $pdo->commit();
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
1 и 2 делаются одним запросом к таблице подписки_пользователей с уникальным ключом (кто, на_кого).
3 и 4 делаются триггером AFTER INSERT.
Проверка необходимости в 5 делается проверкой количества добавленных строк после запроса.
Итого, один запрос к БД, который может вернуть ошибку только при технической ошибке доступа к базе данных, при которой, IMHO, лучше выбросить исключение.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы