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