Patikra, kuri visada teisinga
Šiame straipsnyje
Šioje paslaugoje yra 23 UPDATE sakiniai. Lygiai vienas tikrina, ar ką nors pakeitė. Patikra tokia:
'success' => $n->rowCount() >= 0
rowCount() grąžina 0, kai neatitiko nė viena eilutė. Nulis yra didesnis arba lygus nuliui. Patikra sėkminga, kad ir kas nutiktų.
Kam skirtas sakinys
Jis išsaugo žymimąjį langelį: ar skaitiklio savininkas nori savaitinės suvestinės el. paštu. Adresas yra atskiroje lentelėje, o eilutė joje atsiranda tik žmogui spustelėjus patvirtinimo nuorodą laiške, kurio pats paprašė. Tokią eilutę turi keturi skaitikliai. Aktyvių yra 2 218.
Taigi 99,8 % skaitiklių UPDATE neatitinka nieko. Galinis taškas atsako success: true ir nuostata neišsaugoma, nes nėra kur jos išsaugoti.
Komentaras virš jo teisingas
Trimis eilutėmis aukščiau toje pačioje funkcijoje:
„Tik ten, kur yra patvirtintas grįžtamojo ryšio kelias. Be jo nėra adreso, kuriuo galėtų nueiti laiškas, — o žymimasis langelis žadėtų tai, kas neįvyksta.“
Visiškai teisinga. Kažkas pagalvojo apie šį atvejį, suprato jį ir užrašė priežastį. Tada žemiau esanti eilutė panaudojo >= ten, kur samprotavimas reikalavo >.
Į tai verta pažvelgti tiesiai, nes įprastas paaiškinimas — niekas apie tai nepagalvojo — galimas, bet klaidingas. Mintis yra faile. Suklydo vienas ženklas vietoje, kur neteisinga ir teisinga versijos iš pirmo žvilgsnio atrodo vienodai ir elgiasi vienodai kiekviename teste, turinčiame atnaujintiną eilutę.
Niekas nėra klaidinamas
Šią dalį būtų lengva praleisti, o praleidus įrašas taptų dramatiškesnis ir mažiau teisingas.
Puslapis nerodo žymimojo langelio, jei eilutės nėra. Per vieną ekraną kitur kode, piešiančiame savininko nuostatų langelį, pirmiausia užklausiama ta pati lentelė, o visas blokas praleidžiamas, jei užklausa grįžta tuščia. Todėl savininkas be patvirtinto adreso niekada nemato valdiklio, jo nespusteli ir negauna klaidingo patvirtinimo.
Sugedusi patikra pasiekiama tik tiesiogiai kreipiantis į galinį tašką su galiojančiu prieigos raktu. Taip darantis žmogus gauna success: true ir jokios išsaugotos nuostatos. Tai tikras ir siauras trūkumas.
Kodėl vis tiek verta užrašyti
Funkcija saugi dėl apsaugos, kurios niekas neįvardijo kaip apsaugos. Eilutė, skirta užtikrinti saugumą, jo neužtikrina. Užtikrina atvaizdavimo sąlyga kitoje funkcijoje, kurios komentaras paaiškina, kodėl langelis paslėptas, — ne kad kas nors priklauso nuo to, ar jis liks paslėptas.
Pašalinus ar pertvarkius tą atvaizdavimo sąlygą — pagrįstas veiksmas perkuriant nuostatų skydelį, — trūkumas iš karto tampa matomas, o niekas niekur nesusieja abiejų pakeitimų. Saugumas tikras ir atsitiktinis, o atsitiktinis saugumas dingsta per nesusijusius darbus.
Tas pats kodas vienu failu toliau elgiasi teisingai. Atitinkama svetainių žiedo funkcija klausia, ar eilutė egzistuoja, grąžina false, jei ne, ir visai nevykdo atnaujinimo. Toje lentelėje dabar nulis eilučių, todėl funkcija kaskart iškviesta grąžina false – tai teisingas atsakymas.
Bendras principas
Nė vienoje duomenų bazėje sakinys UPDATE nėra klaida, jei neatitinka nė vienos eilutės. Tai sėkmingas sakinys, kuris nieko nepadarė, ir kiekvienas aukštesnis sluoksnis praneš sėkmę, jei niekas nepaklaus. Dvidešimt du čia esantys sakiniai neklausia, ir daugumai tai tinka: jie atnaujina eilutę, kurios egzistavimą užklausa jau įrodė.
Tas vienas, kuriam reikėjo paklausti, paklausė taip, kad negali nepavykti. rowCount() >= 0 nėra silpna patikra – tai patikros nebuvimas, apsirengęs jos kostiumu, — ir blogiau nei jokios patikros, nes kitas funkciją skaitantis žmogus mato tikrinamą rezultatą ir nustoja ieškoti.
Frazė rowCount() > 0 šiame kode pasitaiko nulį kartų. Būtent šis skaičius vieno ženklo klaidą pavertė įrašo verta tema: ne tai, kad kartą parašyta neteisingai, o tai, kad niekur nebuvo teisingo pavyzdžio palyginti.
Pataisyta 2026 m. rugpjūčio 28 d. Galinis taškas dabar prieš atnaujindamas klausia, ar eilutė egzistuoja, kaip jau darė svetainių žiedo funkcija vienu failu toliau, ir atsako false, jei ne. Akivaizdus vieno ženklo pataisymas — vietoj to lyginti, ar daugiau už nulį, — pirmiausia išmatuotas ir atmestas: tvarkyklė praneša pakeistas, o ne atitikusias eilutes, todėl nustačius langelį į jau esamą reikšmę niekas nesikeičia, ir ta versija praneštų nesėkmę teisingai operacijai. Abi versijos klaidingos priešingomis kryptimis.