Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
909 connectés 

  FORUM HardWare.fr
  Programmation
  PHP

  [Résolu] Comportement bizarre d'une fonction entre PHP5 et PHP8

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Résolu] Comportement bizarre d'une fonction entre PHP5 et PHP8

n°2458772
rufo
Pas me confondre avec Lycos!
Posté le 23-11-2023 à 16:50:38  profilanswer
 

Bonjour,
Je suis tombé sur bug provenant d'une différence entre PHP5 et PHP8 dans l'ajout d'un élément dans un tableau que je ne m'explique pas  :pt1cable:  
 

Code :
  1. function Toto($aTableau)
  2. {
  3.     $iNbPoints = count($aTableau);
  4.     if ($aTableau[0] != $aTableau[$iNbPoints - 1])
  5.     {
  6.         $aTableau[] = $aTableau[0];
  7.         $iNbPoints++;
  8.     }
  9.     print_r($aTableau);
  10.     ...
  11. }


 
$aTableau est un array.
 
Mettons que $aTableau contienne 20 éléments, ils sont donc numérotés dans mon tableau de 0 à 19. Si je passe dans mon test, je vais ajouter un élément à l'indice 20 du coup. En PHP5, c'est bien le cas. En PHP8, bizarrement, mon élément ajouté l'est mais à l'indice 21. Et j'ai pas d'indice 20.  :pt1cable:  
Obligé de faire $aTableau = array_values($aTableau) dans le test après l'ajout de l'élément pour renuméroter de 0 à 20 mes éléments. Je pige pas pourquoi : première fois que je vois ça.
 
Une idée ?
 
Merci :)
 
Edit : ajouter l'élément via array_push() provoque le même comportement. :/


Message édité par rufo le 24-11-2023 à 17:12:54

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
mood
Publicité
Posté le 23-11-2023 à 16:50:38  profilanswer
 

n°2458779
pluj
Posté le 23-11-2023 à 17:52:49  profilanswer
 

Lu,
 
parce que $aTableau contient déjà des trous à la base ? (indices non contigus)
 
Tu utilises unset avant ?

n°2458785
rufo
Pas me confondre avec Lycos!
Posté le 23-11-2023 à 20:07:47  profilanswer
 

Non, si je fais un print_r($aTableau) avant mon if, j'ai bien mes éléments numérotés de 0 à 19.
Le print_r($aTableau) après le test montre les éléments numérotés de 0 à 19 + le 21, sans n° 20... quand je suis en PHP8. En PHP5, j'ai un comportement normal :/


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2458786
mechkurt
Posté le 24-11-2023 à 07:55:26  profilanswer
 

Et si tu fais un var_dump($iNbPoints, $aTableau); entre la ligne 3 et 4 (avant le if et la modification des données), tu as exactement le même output en php 5 et en 8 ?


---------------
D3
n°2458788
FlorentG
Unité de Masse
Posté le 24-11-2023 à 09:00:34  profilanswer
 

Tu dois avoir quelque-chose quelque-part avant qui modifie le tableau, ce qui a pour conséquence l'avancement de l'indice du nouvel élément.
 
Par exemple, si on fait un unset sur le dernier élément :

Code :
  1. $aTableau = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
  2. unset( $aTableau[9] );
  3. Toto($aTableau);


 

Code :
  1. Array
  2. (
  3.     [0] => 0
  4.     [1] => 1
  5.     [2] => 2
  6.     [3] => 3
  7.     [4] => 4
  8.     [5] => 5
  9.     [6] => 6
  10.     [7] => 7
  11.     [8] => 8
  12.     [10] => 0
  13. )


 
On voit bien le trou, c'est un comportement normal. Avec unset, ça a toujours été le cas.
 
Donc le problème est ailleurs : tu dois avoir quelque-chose qui modifie le tableau bien avant, mais dont le comportement a changé entre PHP5 & PHP8. Ça a même pu arriver avec PHP7.

n°2458810
rufo
Pas me confondre avec Lycos!
Posté le 24-11-2023 à 10:50:53  profilanswer
 

mechkurt a écrit :

Et si tu fais un var_dump($iNbPoints, $aTableau); entre la ligne 3 et 4 (avant le if et la modification des données), tu as exactement le même output en php 5 et en 8 ?


Oui.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2458812
rufo
Pas me confondre avec Lycos!
Posté le 24-11-2023 à 10:58:40  profilanswer
 

FlorentG a écrit :

Tu dois avoir quelque-chose quelque-part avant qui modifie le tableau, ce qui a pour conséquence l'avancement de l'indice du nouvel élément.
 
Par exemple, si on fait un unset sur le dernier élément :

Code :
  1. $aTableau = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
  2. unset( $aTableau[9] );
  3. Toto($aTableau);


 

Code :
  1. Array
  2. (
  3.     [0] => 0
  4.     [1] => 1
  5.     [2] => 2
  6.     [3] => 3
  7.     [4] => 4
  8.     [5] => 5
  9.     [6] => 6
  10.     [7] => 7
  11.     [8] => 8
  12.     [10] => 0
  13. )


 
On voit bien le trou, c'est un comportement normal. Avec unset, ça a toujours été le cas.
 
Donc le problème est ailleurs : tu dois avoir quelque-chose qui modifie le tableau bien avant, mais dont le comportement a changé entre PHP5 & PHP8. Ça a même pu arriver avec PHP7.


 
J'ai tout à fait pensé à ça, le coup du unset. Le truc, c'est que mon tableau est passé en paramètre de la fonction, donc, pour moi, c'est par recopie (à moins qu'en PHP8, le passage par défaut serait par référence, mais je ne crois pas).
Et surtout, un print_r($aTableau) avant mon if affiche bien le tableau avec les indices de 0 à 19.
 
Précision, mais je ne pense pas que ça ait une importance. Mon tableau a une forme un peut plus complexe : ses valeurs sont en fait des array associatifs avec 2 valeurs (latitude et longitude)

Code :
  1. function Toto($aTableau)
  2.     {
  3.         $iNbPoints = count($aTableau);
  4.         if (($aTableau[0]['lat'] != $aTableau[$iNbPoints - 1]['lat']) || ($aTableau[0]['lng'] != $aTableau[$iNbPoints - 1]['lng']))
  5.         {
  6.             $aTableau[] = array('lat' => $aTableau[0]['lat'], 'lng' => $aTableau[0]['lng']);
  7.             $iNbPoints++;
  8.         }
  9.         print_r($aTableau);
  10.         ...
  11.     }


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2458813
FlorentG
Unité de Masse
Posté le 24-11-2023 à 10:58:48  profilanswer
 

En y réfléchissant, si les indices doivent être garantis successifs, tu devrais dans tous les cas mettre un array_values. Là tu as trouvé un bug potentiel (qui devrait être couvert par un test unitaire par la suite). Si quelqu'un appel ta fonction avec un array foireux, ton code ne retourne pas quelque-chose de correct. Vaux mieux la jouer safe.

n°2458815
rufo
Pas me confondre avec Lycos!
Posté le 24-11-2023 à 11:06:58  profilanswer
 

C'est bon, j'ai trouvé !
 
Ca venait bien d'un unset mais fait avant l'appel à ma fonction.
 
En gros, j'avais un truc du genre :

Code :
  1. $iNb = count($MonTableau);
  2.     unset($MonTableau[$iNb - 1]);
  3.     $Resultat = Toto($MonTableau);
  4.     function Toto($aTableau)
  5.     {
  6.         $iNbPoints = count($aTableau);
  7.         if ($aTableau[0] != $aTableau[$iNbPoints - 1])
  8.         {
  9.             $aTableau[] = $aTableau[0];
  10.             $iNbPoints++;
  11.         }
  12.         print_r($aTableau);
  13.         ...
  14.     }


 
Vu que la variable $MonTableau est passée par recopie à ma fonction, pour moi, le paramètre $aTableau n'avait pas connaissance de l'indice précédemment effacé par unset() hors de la fonction alors que si :/


Message édité par rufo le 24-11-2023 à 11:10:36

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2458816
FlorentG
Unité de Masse
Posté le 24-11-2023 à 11:08:24  profilanswer
 

Met-nous la raison, si un pauvre hère cherche dans 20 ans, et tombe sur ce topic :o

mood
Publicité
Posté le 24-11-2023 à 11:08:24  profilanswer
 

n°2458817
rufo
Pas me confondre avec Lycos!
Posté le 24-11-2023 à 11:11:54  profilanswer
 

Du reste, manifestement, en PHP5, $aTableau n'a effectivement pas connaissance de l'indice précédemment effacé hors de la fonction alors qu'en PHP8, il ne a connaissance. En tout cas, c'est la conclusion à laquelle j'arrive.


Message édité par rufo le 24-11-2023 à 14:40:49

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2458872
pluj
Posté le 24-11-2023 à 14:39:38  profilanswer
 

Tu peux éventuellement remplacer unset :

Code :
  1. unset($MonTableau[$iNb - 1]);


Par array_splice :

Code :
  1. array_splice($MonTableau, $iNb - 1, 1);

n°2458876
rufo
Pas me confondre avec Lycos!
Posté le 24-11-2023 à 15:07:38  profilanswer
 

Oui, pourquoi pas. Ca va renuméroter les clés de 0 à n.
Mais la conclusion est qu'il y a bien une différence de comportement entre PHP5 et PHP8 concernant la suppression du dernier élément d'un tableau.
L'un va mettre le nouvel élément ajouté au premier indice libre alors que l'autre va le mettre après l'indice de l'élément supprimé. C'est pas intuitif comme comportement je trouve et très piégeux :/


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2458879
FlorentG
Unité de Masse
Posté le 24-11-2023 à 15:12:49  profilanswer
 

À mon avis y'a autre chose encore. Parce qu'en testant sur une 5.6 ou une 8.2, j'ai le même comportement [:johneh] Est-ce que ton tableau est trimballé ailleurs entre le unset, et l'appel à la fonction ?

n°2458882
rufo
Pas me confondre avec Lycos!
Posté le 24-11-2023 à 15:15:21  profilanswer
 

https://www.php.net/manual/fr/function.unset.php
En lisant la doc, vers le bas, je suis tombé sur ce commentaire :  
"Be careful!, unset() element in array advances the internal array pointer one place forward"
 
Mais c'est pas précisé depuis quelle version on a ce comportement.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2458883
rufo
Pas me confondre avec Lycos!
Posté le 24-11-2023 à 15:16:27  profilanswer
 

FlorentG a écrit :

À mon avis y'a autre chose encore. Parce qu'en testant sur une 5.6 ou une 8.2, j'ai le même comportement [:johneh] Est-ce que ton tableau est trimballé ailleurs entre le unset, et l'appel à la fonction ?


Non.
Ma version est du PHP8.0.10 et du PHP5.4.31.
 
Edit : ce matin, j'ai fais des tests dans tous les sens. Si j'enlève le unset() fait sur mon tableau avant d'être passé en paramètre à ma fonction, tout va bien. J'utilise un uWamp. Donc, pour faire mon test, j'ai juste à changer la version de PHP dans une liste déroulante. Ben je vois bien la différence de comportement. Du reste, j'ai fait le même test sur un PHP7.4.33. J'observe le même comportement qu'en PHP8.0.10.


Message édité par rufo le 24-11-2023 à 15:21:02

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2458888
FlorentG
Unité de Masse
Posté le 24-11-2023 à 16:49:43  profilanswer
 

Ah oui du 5.4 ! C'est peut-être entre la 5.4 et la 5.6. On va finir pas trouver :D

n°2458893
rufo
Pas me confondre avec Lycos!
Posté le 24-11-2023 à 17:14:54  profilanswer
 

J'ai mis en résolu mon topic car j'ai compris ce qui se passait et la doc de PHP concernant unset() semble bien mentionner ce comportement.
 
Mais perso, je regrette le comportement plus logique à mon sens de PHP5.4. T'enlèves le dernier élément, tu t'attends franchement à ce que le nouveau empilé prenne l'indice suivant et pas en sauter un. Et le comportement ne devrait pas dépendre de comment tu as enlevé le dernier élément :/


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2458923
spark
Luc ?
Posté le 25-11-2023 à 10:15:32  profilanswer
 

Est-ce que t'as regardé du coté de https://www.php.net/manual/en/function.array-pop.php ?


---------------
Un cycle complet sera une série de 100.
n°2458924
rufo
Pas me confondre avec Lycos!
Posté le 25-11-2023 à 10:25:00  profilanswer
 

Oui, cette fonction n'aurait pas causé le pb. Mais c'est bien ce que je dis : c'est pas normal que suivant la manière dont on enlève le dernier élément, le comportement diffère sur le positionnement de l'index. Un coup, ça le réinitialise, un coup non :/


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2458925
TotalRecal​l
Posté le 25-11-2023 à 10:40:35  profilanswer
 

Les gars, la première fois que j'ai fait du PHP y a 20 ans, l'ado que j'étais s'est dit "quel bordel ce langage, c'est plein de failles potentielles et de comportements chelous, je ne comprends pas que ça soit utilisé par des millions de sites et pas juste des pages persos de bidouilleurs du dimanche sans qu'internet s'effondre toutes les semaines".
Bah là quand je vous lis je me dis que c'est toujours pareil, sauf que maintenant je suis vieux :o

 

Je ne comprends pas qu'un langage puisse altérer entre deux versions le comportement d'un truc utilisé depuis 70 ans comme les tableaux, c'est pas vraiment un truc expérimental :pt1cable:


Message édité par TotalRecall le 25-11-2023 à 10:44:10

---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
n°2458939
FlorentG
Unité de Masse
Posté le 25-11-2023 à 16:07:30  profilanswer
 

Là en l'ocurrence c'est le même merdier en JS avec la propriété length des tableaux :o

n°2459320
TotalRecal​l
Posté le 02-12-2023 à 10:17:18  profilanswer
 

Je me tiens le plus loin possible du JS, mais je sais que sur les chaînes ça donne des résultats rigolo dès qu'on est sur de l'UTF / Unicode (il faut utiliiser un truc bizarre avec des crochets autour de la chaîne pour avoir les "vraies" longueurs), et qu'on peut utiliser l'indexeur pour glisser des trucs après la dernière position quitte à poser quelques undefined en chemin, mais au moins j'imagine que ça s'est toujours comporté pareil... Non ? ... Non :fouyaya: ? Ca a changé de comportement length en js au fil des années ? [:totoz]


Message édité par TotalRecall le 02-12-2023 à 10:17:33

---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
n°2459326
rufo
Pas me confondre avec Lycos!
Posté le 02-12-2023 à 11:50:03  profilanswer
 

Je sais pas, je suis resté en ISO-8859-1 :o


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  PHP

  [Résolu] Comportement bizarre d'une fonction entre PHP5 et PHP8

 

Sujets relatifs
Comportement d'événement Javascript bizarre[SOLVED] fonction super except
fonction illisible dans un fichier annexeChanger une icone en fonction d'une variable ?
Créer et ajouter fonction au menu contextuelFonction exec()
[ksh] Mixture bizarre dans une chaine de caracteres - getoptsproblème de récupération de texte avec une fonction
[Powershell] Variable objet en paramètre de fonction & ValidateSet 
Plus de sujets relatifs à : [Résolu] Comportement bizarre d'une fonction entre PHP5 et PHP8


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR