Il controllo che è sempre vero
In questo servizio ci sono 23 istruzioni UPDATE. Esattamente una di esse guarda se ha cambiato qualcosa. Quel controllo è:
'success' => $n->rowCount() >= 0
rowCount() restituisce 0 quando nessuna riga ha corrisposto. Zero è maggiore o uguale a zero. Il controllo passa qualunque cosa accada.
A che cosa serve l'istruzione
Salva una casella: se il proprietario di un contatore vuole un riepilogo settimanale per posta. L'indirizzo sta in una tabella a parte, e una riga compare lì solo dopo che qualcuno ha cliccato il collegamento di conferma in una mail che aveva chiesto. Quattro contatori hanno una riga così. Quelli attivi sono 2.218.
Per il 99,8 % dei contatori l'UPDATE non trova nulla. Il punto di accesso risponde success: true e l'impostazione non viene salvata, perché non c'è dove salvarla.
Il commento sopra è giusto
Tre righe più in alto, nella stessa funzione:
«Solo dove c'è una via di ritorno confermata. Senza di essa non c'è indirizzo a cui la lettera possa andare — e la casella avrebbe promesso qualcosa che non accade.»
È esattamente così. Qualcuno ha pensato a questo caso, l'ha capito e ha messo per iscritto il ragionamento. Poi la riga sotto ha usato >= dove il ragionamento chiedeva >.
Vale la pena guardarlo dritto negli occhi, perché la spiegazione consueta — nessuno ci ha pensato — è a portata di mano ed è falsa. Il pensiero sta nel file. Ciò che ha fallito è un carattere, in un punto dove la versione sbagliata e quella giusta si somigliano a colpo d'occhio e si comportano uguale in ogni prova che abbia una riga da aggiornare.
Nessuno viene ingannato
Ed ecco la parte che sarebbe facile omettere, e la cui omissione renderebbe questo articolo più drammatico e meno vero.
La pagina non disegna affatto quella casella se la riga manca. Uno schermo più in là, nel codice che compone il riquadro del proprietario, la stessa tabella viene interrogata per prima, e l'intero blocco viene saltato quando l'interrogazione torna vuota. Un proprietario senza indirizzo confermato non vede mai il comando, non lo clicca mai e non riceve mai la conferma falsa.
Il controllo rotto è raggiungibile solo chiamando il punto di accesso direttamente con un gettone valido. Chi lo fa ottiene success: true e nessuna impostazione salvata. È un difetto vero, e stretto.
Perché vale comunque la pena scriverlo
La funzione è sicura grazie a una guardia che nessuno ha annotato come guardia. La riga che esiste per renderla sicura non la rende sicura. Ciò che lo fa è una condizione di disegno in un'altra funzione, il cui commento spiega perché la casella è nascosta — non che qualcosa dipenda dal fatto che resti nascosta.
Togliete o riorganizzate quella condizione — cosa ragionevole rifacendo un pannello di impostazioni — e il difetto diventa visibile all'istante, senza che nulla, da nessuna parte, colleghi i due cambiamenti. La sicurezza è vera, è accidentale, e la sicurezza accidentale è quella che sparisce durante lavori che non c'entrano.
Lo stesso codice lo fa correttamente un file più in là. La funzione equivalente del webring chiede se la riga esiste, restituisce falso quando non c'è, e non emette affatto l'aggiornamento. Quella tabella ha attualmente zero righe, quindi la funzione restituisce falso a ogni chiamata — che è la risposta giusta.
La forma generale
Un UPDATE che non trova righe non è un errore in nessun database. È un'istruzione riuscita che non ha fatto niente, e ogni strato sopra segnalerà successo finché nessuno chiede. Ventidue delle istruzioni qui non chiedono, e per la maggior parte va bene: aggiornano una riga la cui esistenza la richiesta ha già dimostrato.
L'unica che doveva chiedere ha chiesto in un modo che non può fallire. rowCount() >= 0 non è un controllo debole, è l'assenza di controllo travestita da controllo — ed è peggio di nessuno, perché il prossimo che legge la funzione vede un risultato ispezionato e smette di guardare.
L'espressione rowCount() > 0 compare zero volte in questo codice. È quel numero a fare di un refuso qualcosa che merita un articolo: non che sia stato scritto male una volta, ma che non esistesse da nessuna parte un caso corretto con cui confrontarlo.
Corretto il 28 agosto 2026. Il punto di accesso chiede ora se la riga esiste prima di scrivere — come già faceva la funzione del webring un file più in là — e altrimenti risponde falso. La correzione ovvia di un carattere, controllare invece «maggiore di zero», è stata prima misurata e poi scartata: il driver riporta le righe cambiate, non quelle trovate. Chi mette la casella sul valore che ha già non cambia nulla — e quella versione avrebbe segnalato un fallimento per un'operazione che andava bene. Entrambe le versioni sono sbagliate, in direzioni opposte.