Проверка, которая всегда истинна
В этой службе 23 инструкции UPDATE. Ровно одна из них смотрит, изменила ли она что-нибудь. Эта проверка такая:
'success' => $n->rowCount() >= 0
rowCount() возвращает 0, когда ни одна строка не подошла. Ноль больше или равен нулю. Проверка проходит, что бы ни случилось.
Для чего эта инструкция
Она сохраняет галочку: хочет ли владелец счётчика недельную сводку по почте. Адрес лежит в отдельной таблице, и строка появляется там только после того, как кто-то нажал ссылку подтверждения в письме, о котором сам попросил. Такая строка есть у четырёх счётчиков. Активных — 2 218.
Значит, для 99,8 % счётчиков UPDATE не попадает никуда. Конечная точка отвечает success: true, а настройка не сохраняется, потому что сохранять её негде.
Комментарий над ней верен
Тремя строками выше, в той же функции:
«Только там, где есть подтверждённый обратный путь. Без него нет адреса, куда могло бы уйти письмо, — и галочка пообещала бы то, чего не происходит.»
Это ровно так. Кто-то подумал об этом случае, понял его и записал рассуждение. А затем строка ниже употребила >= там, где рассуждение требовало >.
На это стоит посмотреть прямо, потому что обычное объяснение — никто не подумал — лежит под рукой и оно ложно. Мысль есть в файле. Подвёл один знак, в месте, где неправильная и правильная версия выглядят с первого взгляда одинаково и ведут себя одинаково в любой проверке, у которой есть строка для обновления.
Никого не обманывают
Вот часть, которую легко было бы опустить, и её пропуск сделал бы эту запись драматичнее и менее правдивой.
Страница вовсе не рисует эту галочку, если строки нет. Экраном дальше, в коде, который собирает блок владельца, ту же таблицу спрашивают первой, и весь блок пропускается, когда запрос возвращается пустым. Владелец без подтверждённого адреса никогда не видит этот переключатель, никогда его не нажимает и никогда не получает ложного подтверждения.
Сломанная проверка достижима только прямым обращением к конечной точке с действующим токеном. Тот, кто это сделает, получит success: true и никакой сохранённой настройки. Это настоящий изъян, и узкий.
Почему это всё же стоит записать
Возможность безопасна благодаря стражу, которого никто не записал как стража. Строка, существующая ради безопасности, её не обеспечивает. Обеспечивает условие отрисовки в другой функции, чей комментарий объясняет, почему галочка спрятана, — но не то, что от её спрятанности что-то зависит.
Уберите или перестройте это условие — разумное дело при переделке панели настроек — и изъян становится виден мгновенно, а ничто нигде не связывает эти две правки. Безопасность настоящая, она случайная, а случайная безопасность — та, что исчезает во время постороннего труда.
Тот же код делает это правильно одним файлом дальше. Соответствующая функция вебринга спрашивает, есть ли строка, возвращает ложь, если нет, и вовсе не отправляет обновление. В той таблице сейчас ноль строк, значит, функция возвращает ложь при каждом вызове — и это правильный ответ.
Общая форма
UPDATE, не попавший ни в одну строку, ни в одной базе не ошибка. Это успешная инструкция, которая ничего не сделала, и каждый слой выше отчитается об успехе, пока никто не спросит. Двадцать две здешние инструкции не спрашивают, и для большинства это нормально: они обновляют строку, существование которой запрос уже доказал.
Единственная, которой надо было спросить, спросила так, что провалиться невозможно. rowCount() >= 0 — это не слабая проверка, это отсутствие проверки в костюме проверки — и это хуже, чем никакой, потому что следующий, кто прочтёт функцию, увидит осмотренный результат и перестанет смотреть.
Выражение rowCount() > 0 встречается в этом коде ноль раз. Именно это число делает из опечатки нечто достойное записи: не то, что один раз написали не так, а то, что нигде не было правильного случая, с которым это можно было бы сверить.
Исправлено 28 августа 2026 года. Конечная точка теперь спрашивает, есть ли строка, прежде чем писать — так, как функция вебринга одним файлом дальше делала всегда, — и иначе отвечает ложью. Очевидное исправление в один знак, проверять вместо этого «больше нуля», было сначала измерено и отвергнуто: драйвер сообщает число изменённых строк, а не найденных. Тот, кто ставит галочку в значение, которое у неё уже есть, ничего не меняет — и та версия сообщила бы о неудаче для действия, с которым всё было в порядке. Обе версии неверны, только в противоположные стороны.