Bienvenue sur PEBKAC.fr, le site qui recense les anecdotes où l’on se moque des utilisateurs ne maîtrisant pas l’outil informatique. PEBKAC est un acronyme signifiant « Problem Exists Between Keyboard And Chair ».
Le problème se situe entre la chaise et le clavier : soumettez vos histoires, donnez votre avis !
Ce site n'est pas le site original pebkac.fr. Je publie ici la liste des PEBKAC que j'ai pu sauvegarder avant que le site original ne soit mis hors ligne.
Vu à l'instant sur un site anglophone d'entraide entre programmeurs, une énième demande d'aide pour un script PHP qui ne fonctionne pas… Comme d'habitude, on retrouve l'utilisation des fonctions mysql_* pourtant obsolètes depuis bien longtemps.
Mais cette fois ils ont décidé d'innover : en effet, il semble y avoir une implémentation "maison" du AUTO_INCREMENT en PHP, vu que c'est apparemment bien plus amusant de réinventer la roue que d'utiliser une fonction proposée en standard par MySQL. Et le pire, c'est que c'était ce point justement qui empêchait son code de fonctionner correctement. PEBKAC.
PEBKAC #9284 proposé par Nest le 18/01/2014 | 25 commentaires | 👍🏽 👎🏽 +91
Bof le concept d'un site d'entraide … c'est d'aider les gens, pas de clasher ce qu'ils font ! Parce qu'à priori si ils viennent demander, c'est qu'ils savent pas comment faire mieux

Après là où on peut critiquer, c'est les gens qui viennent poser une question façon «fait mon devoir maison à ma place» et/ou avec aucun effort sur l'écriture/mise en forme. Mais ici c'est pas vraiment ce que tu décris, donc un bon CTLP pour moi.
Commentaire #125749 écrit par yomama le 18/01/2014 à 13h21 | 👍🏽 👎🏽
Moi j'ai une manivelle sur mon serveur mySQL pour changer l'ID à la main ^^
Arf faut bien débuter aussi ça coule pas de source quand on commence. (enfin bon c'est vrai que les tutos ça peut se suivre autrement quand diagonale)
Commentaire #125758 écrit par wut le 18/01/2014 à 14h15 | 👍🏽 👎🏽
Bah, PHP, le langage fait par des PEBKACs, pour des PEBKACs.
Commentaire #125765 écrit par b0fh le 18/01/2014 à 15h39 | 👍🏽 👎🏽
Le problème de l'AUTO_INCREMENT sous MySQL, c'est pour récupérer l'identifiant qui vient d'être créé pour pouvoir le réutiliser (dans des tables intermédiaires par exemple)..

Alors certes, nous avons la fonction mysql_insert_id qui récupère le dernier identifiant inséré et la possibilité d'empaqueter tout ça dans une transaction pour éviter les problèmes liés à l'exécution de plusieurs insert en parallèle, mais ce n'est du coup pas forcément accessible à un novice.

Pour un débutant (et même d'autres), une solution simple est de gérer l'incrémentation de ses identifiants lui-même, et ainsi pouvoir les réutiliser facilement. Mine de rien, réinventer la roue quand on commence juste à aborder un langage permet aussi de progresser.

Bref, comme dit plus haut, s'il demande, c'est justement qu'il ne sait pas... et comme on ne sait pas s'il est de bonne volonté ou non, difficile de critiquer ouvertement son erreur.
Commentaire #125767 écrit par Morrock le 18/01/2014 à 15h45 | 👍🏽 👎🏽
@Morrock je vois pas pourquoi la fonction "mysql_insert_id" serait pas accessible à un novice, surtout que dans sa question c'était justement ça, en fait son code commençait par récupérer l'ID via "mysql_insert_id" (qui ne fonctionnait pas vu qu'avant de pouvoir faire ça il faut déjà avoir fait une requête INSERT dans la DB) pour ensuite faire un INSERT avec l'ID précédemment récupéré+1 et la donnée qu'il souhaite insérer (du moins c'est censé être comme ça, mais ça ne fonctionnait pas pour les raisons citées juste avant).

Et personnellement je trouve que c'est bien plus facile de laisser MySQL gérer tous les "AUTO_INCREMENT" (et si nécessaire utiliser "mysql_insert_id" pour obtenir le dernier ID après une requête INSERT).
Commentaire #125771 écrit par Nest le 18/01/2014 à 16h13 | 👍🏽 👎🏽
J'ai une confiance limitée dans le mysql_insert_id. La dernière fois qu'il s'est planté, j'ai été bon pour faire un +1 sur près de 300 lignes...
Commentaire #125773 écrit par Link le 18/01/2014 à 16h28 | 👍🏽 👎🏽
Je n'ai pas dit que la fonction mysql_insert_id n'était pas accessible à un novice. J'ai dit que pour gérer le tout correctement, il fallait passer cette fonction dans une transaction, enchaînant ainsi insert et mysql_insert_id pour être sûr de récupérer le bon id. C'est l'utilisation des transactions qui n'est pas forcément accessible à un novice.

Si tu le fais en deux étapes distinctes (sans transaction donc), tu as un risque (plus ou moins grand, on est d'accord, mais existant) que plusieurs insert se fassent quasiment en simultané, et dans ce cas, au moment où tu fais le mysql_insert_id, tu risque de récupérer l'identifiant d'une donnée insérée par un autre script qui s'exécute en parallèle. Le cas est très rare, mais doit être pris en considération.
Commentaire #125776 écrit par Morrock le 18/01/2014 à 16h36 | 👍🏽 👎🏽
C'est en partie ce que j'ai dit : mysql_insert_id seul n'est pas fiable, d'où le fait que je l'emballe toujours dans un système de transactions (voire que je préfère m'en passer).

Je préfère de loin le système de PostGreSQL et l'utilisation de la commande RETURNING à la fin d'un INSERT.
Commentaire #125777 écrit par Morrock le 18/01/2014 à 16h39 | 👍🏽 👎🏽
http://fr.wikipedia.org/wiki/Php#Historique
Commentaire #125778 écrit par aDev le 18/01/2014 à 16h47 | 👍🏽 👎🏽
...autrement qu'EN diagonale...

Erreur qui donnerait une crise cardiaque à un certain habitué des lieux. ;)
Commentaire #125784 écrit par Hecatian le 18/01/2014 à 19h07 | 👍🏽 👎🏽
Elle n'est pas dépréciée cette fonction en PHP ?
Sinon faut faire directement en SQL SELECT LAST_INSERT_ID();
Commentaire #125790 écrit par juu le 18/01/2014 à 21h41 | 👍🏽 👎🏽
Faux, le last_insert_id dépend de la session utilisateur, donc même si un autre script vient insérer des éléments, tu obtiendras seulement l'id de la ligne que ton script a insérée.
Commentaire #125791 écrit par juu le 18/01/2014 à 21h48 | 👍🏽 👎🏽
Utilser la fonction SELECT LAST_INSERT_ID() a exactement les mêmes défauts que la fonction mysql_insert_id...

Et sinon, tu as raison, les fonctions mysql_* en php sont toutes dépréciées et il est plutôt conseillé de passer maintenant par les méthodes PDO.
Commentaire #125818 écrit par Morrock le 19/01/2014 à 09h25 | 👍🏽 👎🏽
Je viens de relire la doc : la fonction est liée à la connexion à la base. Ils doivent l'avoir rajouté plus ou moins récemment puisque je suis sûr d'avoir déjà rencontré l'erreur il y a quelques temps.

Cela dit, un comportement de script plus ou moins aléatoire ou mal pensé peut couper la connexion entre l'insert et le last_insert_id, et dans ce cas, il ne fonctionne plus. (Bon, dans ce cas, c'est un PEBKAC, on est d'accord, mais j'ai déjà vu des scripts qui recréaient la connexion à chaque requête.)

Dons au temps pour moi, bien utilisé dans sa version actuelle, ça devrait en effet fonctionner.
Commentaire #125820 écrit par Morrock le 19/01/2014 à 09h37 | 👍🏽 👎🏽
Arf, trop tard pour éditer... voir ci-dessous pour le complément de réponse ^^
Commentaire #125821 écrit par Morrock le 19/01/2014 à 09h38 | 👍🏽 👎🏽
Avant, mes scripts marchaient de la manière suivante : ouverture BDD, requête 1, requête 2, ... requête n, fermeture BDD.

Maintenant, je fait systématiquement : ouverture BDD, requête 1, fermeture BDD, ouverture BDD, requête 2, fermeture BDD, ... , ouverture BDD, requête n, fermeture BDD,

Dans ce dernier cas, je n'ai plus eu de problème à signaler avec le mysql_insert_id. Pifenmoins, j'essaie au maximum de m'en passer.
Commentaire #125827 écrit par Link le 19/01/2014 à 11h09 | 👍🏽 👎🏽
mysql_insert_id serait donc lié à la session php et pas à la session MySQL, ce qui ferait une grosse différence de fonctionnement entre les deux méthodes.

Tu illustres ici mon exemple ci-dessous (un script qui recrée une connexion à chaque requête... du coup, je t'ai traité de PEBKAC là-dessous ^^).
Le fait d'ouvrir et fermer constamment ta connexion à la base de données doit augmenter le temps d'exécution de tes scripts, non?
Commentaire #125831 écrit par Morrock le 19/01/2014 à 13h22 | 👍🏽 👎🏽
Tout d'abord, je ne suis aucunement expert en MySQL. Quand j'étais à la fac, j'ai eu dans les 15 heures de cours/TP sur à la fois le HTML, PHP et MySQL, alors que je n'avais absolument aucunes bases dans ces 3 domaines. Mon Master regroupait deux formations différentes : ceux ayant fait informatique, et les autres électronique/automatique (moi). Heureusement que mon binôme venait d'info...

Depuis je me suis plus au moins auto-formé, à la maison comme au boulot, et j'ai eu quelques conseils d'un collègue bien plus calé la dedans, qui m'a expliqué comment bien définir ses structures de tables et optimiser ses requêtes.

C'est justement ce collègue qui m'a conseillé d'ouvrir et fermer la connexion à chaque requête. Cela est particulièrement utile quand je travaille sur deux bases simultanément. Pour les performances en mono-base, je ne sais pas si c'est plus rapide, je pense que c'est plutôt le contraire.
Commentaire #125833 écrit par Link le 19/01/2014 à 14h11 | 👍🏽 👎🏽
Pour le coup, ça arrive à m'en donner une, c'est dire... u_u
Commentaire #125842 écrit par blag le 19/01/2014 à 22h57 | 👍🏽 👎🏽
Normalement, on évite fortement d'ouvrir/fermer les connexion... :/
(pas pour rien qu'on utilise des options de "keep alive connexion" pour éviter les latences sur les site de bonne taille)

Dans le cas d'utilisation du last ID, le plus simple et le plus adapté est en effet la procédure stocké (qui implémente la transaction) : tu créer un petit script SQL qui est déjà compilé et qui se gère de manière atomique coté BDD (gaf quand même à MyISAM qui gère pas l'état quantique de la table "pendent" l'exécution, d'où l'usage de InnoDB pour ce genre de chose).
Ce script est capable de travailler sur plusieurs tables sans se faire interrompre en écriture pas une autre requête, donc ton LAST_INERT_ID est belle est bien celui de la transaction en cours, que tu peut même retourner à la fin comme résultat de ton appelle à la procédure.
Commentaire #125843 écrit par blag le 19/01/2014 à 23h07 | 👍🏽 👎🏽
@Link : point de vue formation, je suis ingénieur agronome... on peut difficilement dire que j'ai eu beaucoup de cours d'informatique (même si j'ai choisi une spécialité Management de systèmes d'Informations, ça reste une petite initiation et pas de formation poussée). Et je ne me prétend d'ailleurs pas expert en MySQL.
Mais ayant fait du développement web une de mes missions principales actuellement, j'essaie au maximum de devenir/rester compétent dans le domaine. Mon but n'était pas de t'attaquer, et c'était une vraie question sur la vitesse de ton script. C'est donc bien ce que je pensais, c'est moins rapide (donc plus long...)

Pour le reste, voir la blabla de blag avec lequel je suis totalement d'accord.
Commentaire #125844 écrit par Morrock le 20/01/2014 à 00h15 | 👍🏽 👎🏽
@Morrock: Sans transactions, dans le cas où ta connexion coupe au milieu de tes opérations en base, c'est de toute façon relativement problématique en général...
Commentaire #125853 écrit par triman le 20/01/2014 à 11h50 | 👍🏽 👎🏽
Ca dépend pourquoi la connexion coupe. Si c'est une erreur, on est d'accord. Si c'est le cas d'un script fonctionnant comme celui de Link plus haut, ce n'est pas en soi un problème.
Commentaire #125871 écrit par Morrock le 20/01/2014 à 13h22 | 👍🏽 👎🏽
Jusqu'à présent, demander de l'aide lorsqu'on avait un problème était justement le contraire du PEBKAC.
Je suis étonné du nombre de BEDP ici. :/
Commentaire #125886 écrit par Peredur le 20/01/2014 à 14h03 | 👍🏽 👎🏽
T'as du confondre avec JAVA.
Commentaire #125971 écrit par wut le 20/01/2014 à 20h00 | 👍🏽 👎🏽