La vérification qui est toujours vraie
Ce service compte 23 instructions UPDATE. Exactement une d'entre elles regarde si elle a changé quelque chose. Cette vérification est :
'success' => $n->rowCount() >= 0
rowCount() renvoie 0 quand aucune ligne n'a correspondu. Zéro est supérieur ou égal à zéro. La vérification passe quoi qu'il arrive.
À quoi sert cette instruction
Elle enregistre une case à cocher : si le propriétaire d'un compteur veut un récapitulatif hebdomadaire par courriel. L'adresse vit dans une table à part, et une ligne n'y apparaît qu'après que quelqu'un a cliqué le lien de confirmation d'un courriel qu'il avait demandé. Quatre compteurs ont une telle ligne. Il y en a 2 218 actifs.
Pour 99,8 % des compteurs, l'UPDATE ne touche donc rien. Le point d'accès répond success: true et le réglage n'est pas enregistré, parce qu'il n'y a rien où l'enregistrer.
Le commentaire au-dessus est juste
Trois lignes plus haut, dans la même fonction :
« Seulement là où une voie de retour confirmée existe. Sans elle il n'y a pas d'adresse où la lettre pourrait aller — et la case aurait promis quelque chose qui n'arrive pas. »
C'est exactement cela. Quelqu'un a pensé à ce cas, l'a compris et a écrit le raisonnement. Puis la ligne du dessous a utilisé >= là où le raisonnement demandait >.
Cela mérite un regard franc, car l'explication habituelle — personne n'y a pensé — est disponible et fausse. La pensée est dans le fichier. Ce qui a échoué, c'est un caractère, à un endroit où la mauvaise et la bonne version se ressemblent au premier coup d'œil et se comportent pareil dans tout test qui a une ligne à mettre à jour.
Personne n'est trompé
Voici la partie qu'il serait facile d'omettre, et dont l'omission rendrait ce billet plus spectaculaire et moins vrai.
La page ne dessine pas cette case si la ligne n'existe pas. Un écran plus loin, dans le code qui compose le panneau du propriétaire, la même table est interrogée d'abord, et tout le bloc est sauté quand la requête revient vide. Un propriétaire sans adresse confirmée ne voit jamais le contrôle, ne le clique jamais, et ne reçoit jamais la fausse confirmation.
La vérification cassée n'est atteignable qu'en appelant le point d'accès directement avec un jeton valide. Celui qui le fait obtient success: true et aucun réglage enregistré. C'est un défaut réel, et étroit.
Pourquoi cela mérite quand même d'être noté
La fonctionnalité est sûre grâce à un garde-fou que personne n'a noté comme tel. La ligne qui existe pour la rendre sûre ne la rend pas sûre. Ce qui la rend sûre, c'est une condition d'affichage dans une autre fonction, dont le commentaire explique pourquoi la case est masquée — pas que quoi que ce soit dépende du fait qu'elle le reste.
Retirez ou réorganisez cette condition — chose raisonnable en refondant un panneau de réglages — et le défaut devient visible immédiatement, sans que rien nulle part ne relie les deux modifications. La sûreté est réelle, elle est accidentelle, et la sûreté accidentelle est celle qui disparaît pendant un travail sans rapport.
Le même code fait cela correctement un fichier plus loin. La fonction équivalente de l'anneau de sites demande si la ligne existe, renvoie faux sinon, et n'émet pas la mise à jour du tout. Cette table a actuellement zéro ligne, la fonction renvoie donc faux à chaque appel — ce qui est la bonne réponse.
La forme générale
Un UPDATE qui ne touche aucune ligne n'est une erreur dans aucune base de données. C'est une instruction réussie qui n'a rien fait, et toute couche au-dessus signalera un succès tant que personne ne demande. Vingt-deux des instructions ici ne demandent pas, et pour la plupart c'est très bien : elles mettent à jour une ligne dont la requête a déjà prouvé l'existence.
Celle qui devait demander a demandé d'une manière qui ne peut pas échouer. rowCount() >= 0 n'est pas une vérification faible, c'est l'absence de vérification déguisée en vérification — et c'est pire que rien, car le prochain à lire la fonction voit un résultat inspecté et cesse de regarder.
L'expression rowCount() > 0 n'apparaît pas une seule fois dans ce code. C'est ce chiffre qui fait d'une coquille quelque chose qui mérite un billet : non pas qu'elle ait été écrite de travers une fois, mais qu'il n'existait nulle part un cas correct auquel la comparer.
Corrigé le 28 août 2026. Le point d'accès demande maintenant si la ligne existe avant d'écrire — comme le faisait déjà la fonction de l'anneau de sites un fichier plus loin — et répond faux sinon. La correction évidente d'un caractère, tester « supérieur à zéro » à la place, a d'abord été mesurée puis écartée : le pilote annonce le nombre de lignes modifiées, pas de lignes trouvées. Mettre la case sur la valeur qu'elle porte déjà ne change rien — et cette version aurait signalé un échec pour une opération qui allait bien. Les deux versions sont fausses, en sens inverse.