Espace membres

Bonjour Anonyme

Inscription

Email :
Mot de passe :

Mot de passe oublié ?

Nos scripts

MySpeach

MySpeach est un chat php sans base de donnée, rapide, léger et facile à prendre en main. DEMO

MyPHPUpload

MyPHPUpload est un script d'upload sécurisé écrit en PHP. DEMO

GrapAgenda

Agenda PHP et MySQL avec comptes utilisateurs et administration. DEMO

Livre PHP

création de site

Les erreurs communes en PHP

Cours / tutoriel écrit le 16-06-2010 par sky

Texte de Stéphane Pineau.
Sont site : http://steph.pineau.free.fr/php/index.php

Quand les commentaires sont interprétés...

Sous PHP3, ne vous hasardez pas à mettre un <? et encore moins un ?> dans un commentaire de script (simple ou multi-lignes). Car il semblerait que la recherche des tags ouvrants et fermant aient la priorité sur les tags d'ouverture de commentaire. Du coup quand PHP trouve un ?> dans un commentaire il s'embrouille légèrement. Ceci s'applique également d'ailleurs quand l'un de ces deux tags se retrouve dans une chaine de caractères encadrée par des guillemets ou des apostrophes (simple quote).

Afficher le contenu d'une variable incluse dans une chaine de caractères.

PHP n'interprête le contenu d'une variable dans une chaine de caractères que si cette dernière est encadrée par des guillemets. Si la chaine est encadrée par des apostrophes (simple quote), il affiche le nom de la variables. Soit par exemple avec $TOTO="JEUDI"

echo "Aujourd'hui nous sommes $TOTO";

Affiche Aujourd'hui nous sommes JEUDI

echo 'Aujourd'hui nous sommes $TOTO';

Affiche Aujoutd'hui nous sommes $TOTO

Compter le nombre d'éléments d'un tableau passé à un script depuis un formulaire

Soit un formulaire utilisant une variable tableau pour contenir les valeurs :

<FORM METHOD='POST' ACTION='script.php'>
<INPUT TYPE='text' NAME='MONTABLEAU[]'>
<INPUT TYPE='text' NAME='MONTABLEAU[]'>
<INPUT TYPE='text' NAME='MONTABLEAU[]'>
</FORM>

Pour connaitre le nombre d'éléments contenus dans MONTABLEAU[] la première idée est d'utiliser la fonction Count :$X=count($MONTABLEAU);). Si on teste toutefois on s'appercevra que dans l'exemple donné $X contiendra toujours la valeur 3 correspondant au nombre de champs du formulaire. On en déduit donc que le formulaire soit rempli entièrement ou nom, PHP passe un tableau ayant réservé un espace pour chaque champ. Pour connaitre le nombre réel d'éléments il faut donc utiliser une boucle, qui teste chaque élément du tableau pour voir s'il est vide ou non :

$NB_ELEMENTS=0;
For ($X=0;$X<count($MONTABLEAU);$x++){
If (Strlen(Trim($MONTABLEAU[$X]))==0):
$NB_ELEMENTS++;
endif;
}


Un test conditionnel qui donne des résultats bizarres

Un grand classique du genre. Dans un script il arrive fréquemment que l'on teste que deux variables soient de valeurs identiques. Et parfois, sans qu'on comprenne pourquoi, le test foire ou quelques lignes après le test on se retrouve avec des valeurs incorrectes dans un variable. En général il est inutile de chercher bien loin, on aura simplement oublié de signe = dans le test conditionnel.

L'opérateur d'équivalence est doit être indiqué par un double signe = soit == (ou un triple signe = à partir de PHP4 pour vérifier également l'équivalence du typage des variables), un signe égal seul correspond lui au signe d'affectation.

If ($x=$y):

génère donc un problème, puisqu'au lieu de tester l'équivalence entre $x et $y PHP affecte la valeur de $y à $x. La syntaxe correcte est donc

if ($x==$y) :
.

Une boucle qui donne des résultats bizarres....

Encore une erreur sournoise...cette fois avec une boucle. Soit l'exemple suivant :

for($x=0; $x<10; $x++) ;
{
echo "La valeur de x est = $x<br>\r\n";
}


Ce bout de code n'affichera qu'une seule fois la phrase "La valeur de x est 10" et la valeur sera toujours 10. L'erreur vient tout simplement du point virgule placé à la fin de la ligne for(...) et encore une fois des syntaxe permissive de PHP. Dans ce cas de figure PHP comprend qu'il doit exécuter 10 le code contenu tout de suite après le for() et jusqu'au point-virgule. Comme en l'occurence il n'y a rien entre les deux, la boucle s'exécute bien jusqu'à ce que $x égale 10, mais ne fait rien d'autre.
Le programme se poursuit ensuite tout à fait normalement (la présence d'accolades ne se référant à aucune instruction de bloc ne le gêne pas). Il affiche donc la dernière valeur de $x (incrémentée dans la boucle for qui a tourné à vide), soit 10.

Une parenthèse bien mal placée...

Et encore une erreur liée à une problème de syntaxe...Personnellement il m'est arrivé de la faire plusieurs fois. Le problème se pose tout bêtement avec une parenthèse mal placée dans un test :

$Txt="Bonjour";
IF (Strlen($Txt==7)):
echo "Ok";
Else:
echo "Not Ok";
Endif;

Ce test destiné à vérifier la longueur d'une chaine renverra toujours "Ok" sous PHP3, quelque soit la longueur de $Txt, et ce tout simplement parceque la parenthèse fermante de la fonction Strlen est placée après le "7" et non après le "$Txt". La fonction n'est pas gênée de recevoir "$Txt==7" en paramètre, il n'y a pas de message d'erreur mais elle se contente de renvoyer 0 pour signaler qu'elle n'a pu déterminer la longueur du paramètre car elle ne l'a pas reconnu comme une chaine.
Comme par ailleurs telle qu'écrite la ligne "IF..." revient à tester le retour de la fonction et non l'équivalence avec une valeur, et que la valeur 0 d'erreur retournée équivaut à un "True" la condition est toujours vérifiée.
Ici l'exemple utilise la fonction "strlen" mais cette erreur peut se produire avec bien d'autres fonctions que l'on tente de comparer avec une valeur. A noter que sous PHP4 cette syntaxe génère une erreur.

Syntaxes alternées dans des instructions conditionnelles imbriquées.

Le parser PHP3 n'apprécie guère dans les test conditionnels imbriqué l'utilisation des deux types de syntaxe autorisées à savoir soit l'utilisation d'accolades pour séparer les blocs et l'utilisation d'un : et des instructions else, elseif, endif. Exemple de syntaxe à problème :

If ($X==$Y):
if ($W>$Y){
......
}
Else
while ($Z<$W):
....
Endwhile;
Endif;


"Variable passed to each() is not an array or object in..."

La plupart du temps ce message d'erreur s'affiche lorsque l'on tente d'accéder à un tableau vide. Par exemple le code suivant déclenche ce message si $TABLEAU[] ne contient aucun élément.

ksort($TABLEAU);
While (List($KEY,$VALUE)=each($TABLEAU)):
echo ("$KEY -> $VALUE");
EndWhile;

Pour éviter ce problème, ajoutez un test sur le nombre d'éléments contenus dans le tableau via la fonction count (NB: voir aussi Compter le nombre d'éléments d'un tableau passé à un script depuis un fomulaire) :

if (count($TABLEAU)>0):
ksort($TABLEAU);
While (List($KEY,$VALUE)=each($TABLEAU)):
echo ("$KEY -> $VALUE");
EndWhile;
Endif;


Utilisation de la fonction strpos()

La fonction strpos() permet de connaitre la position de la première occurence d'une chaine contenu dans une autre chaine. Toutefois comme le premier caractère d'une chaine à pour numéro d'ordre 0 et non 1, se pose le problème de la différenciation entre une chaine contenant la chaine recherchée en début (donc la fonction retourne 0) et une chaine ne contenant pas la chaine recherchée. La syntaxe suivante est donc incorrecte.

$POS=strpos($ChercheDans,$LaChaine,$Apartir_du_Caract._n°);
if ($POS==0):
.....
Endif;

La fonction ne peut renvoyer 0 (valeur généralement utilisée en retour pour signaler un echec) puisque cette valeur 0 correspond justement à la position réelle du 1er caractère. Aussi PHP retourne une chaine de caractère contenant 'false' si la recherche échoue, et une valeur numérique si elle a aboutie (la chaine recherchée est trouvée dans la chaine principale). Pour obtenir un test correct il faut donc tester le type de la valeur retournée avant de poursuivre les traitements :

$POS=strpos($ChercheDans,$LaChaine,$Apartir_du_Caract._n°);
if (!is_string($POS)):
// Cette syntaxe est correcte. On n'entre dans
// la boucle que si la valeur retournée
// est une valeur numérique.
.....
Endif;

Une autre astuce, s'il s'agit simplement de vérifier l'existence d'une sous-chaine dans une chaine, donc qu'aucun traitement sur la chaine principale n'est conditionnée par la position de la sous-chaine (comme couper la chaine à partir de la sous-chaine), et que par ailleurs on ne souhaite pas utiliser les fonctions EREG_xxx basées sur les expressions régulières :

IF (strpos(" ".$ChercheDans,$LaChaine,$Apartir_du_Caract._n°) >0) :
// Notez l'espace ajouté au début de
// la chaine. Ainsi sauf si la sous-chaine commence
// également par un espace, la condition n'est
// vérifiée effectivement que si la
// la sous-chaine est trouvée et ce sans avoir
// tester le type de la valeur renvoyée.
...


Contenu tronqué d'une variable récupérée en tant que valeur dans un champ de formulaire

Il est parfois utile de récupérer le contenu d'une variable PHP dans un champ de formulaire. Toutefois il y a de nombreaux pièges qui ont pour origine en fait la syntaxe HTML. Partons d'un exemple simple, en supposant que la page suivante récupère via l'url par exemple une variable $MAVAR passée en paramètre dont le contenu est Ceci est mon texte.

<HTML>
<HEAD></HEAD>
<BODY>
<form action='result.php' method='post'>
<input type='text' name='MAVAR_ENSORTIE' value=<?php echo $MAVAR; ?> >
</BODY>
</HTML>

Lors de la validation de ce formulaire on s'attend donc à ce que le formulaire affiche dans la zone de saisie le contenu de $MAVAR soit "Ceci est mon texte". Pourtant ce n'est pas le cas, le champ contient uniquement "Ceci". La raison est simple. En HTML, les navigateurs interprete tout ce qui suit le signe = placé à droite d'un paramètre comme la valeur d'un paramètre et ce jusqu'au premier espace rencontré. Les caractères suivant sont considérés comme le nom du paramètre suivant. Ceci s'applique du moins par défaut quand ce qui suit le signe = n'est pas encadré par des guillemets ou des apostrophes (simple quote) ' '. Ce qui est le cas dans l'exemple. Pour remédier à ce problème on rajoute simplement les apostrophes autour de la variable. NB: On utilisera toujours les apostrophes de préférence aux guillemets :

<HTML>
<HEAD></HEAD>
<BODY>
<form action='result.php' method='post'>
<input type='text' name='MAVAR_ENSORTIE' value='<?php echo $MAVAR; ?>' >
</BODY>
</HTML>

Maintenant se pose un autre problème... que va-t'il se passer si la variable $MAVAR contient une apostrophe, par exemple "Ceci est la page de Steph' - Bonjour !"? PHP va générer et envoyer la page suivante après avoir remplacé le contenu de $MAVAR.

<input type='text' name='MAVAR_ENSORTIE' value='Ceci est la page de Stéph' - Bonjour '<

Le navigateur applique dans ce cas la règle que si le première caractère qui suit le signe = est une apostrophe, tout ce qui suit jusqu'à la prochaine apostrophe correspond à la valeur du paramètre, et ce qui suit ensuite est un nouveau paramètre. Du coup en appliquant bêtement ce principe le champ de saisie ne va afficher que "Ceci est la page de Stéph". Et il s'arrête là puisque que le navigateur vient de rencontrer une apostrophe, celle contenue dans notre variable. Pour lui tout ce qui suit n'a plus rien à voir.

La norme HTML à toutefois prévu ce cas de figure... Elle veut que les caractères réservés pour elle même tels que les apostrophes, les guillemets ou les signes < et > soient remplacés par leur valeur décimale lorsqu'ils doivent être utilisés comme valeur d'un paramètre d'une balise. Attention, il ne s'agit pas de les remplacer par leur équivalent en codage internationnal comme &gt; pour le signe > cette syntaxe étant réservée pour l'affichage des caractères dans la page HTML et non pour leur utilisation dans les balises. On utilisera ici la syntaxe &#nn ou nn est la valeur décimale du caractère. Il convient donc de demander à PHP de remplacer dans $MAVAR les caractères problématiques, à savoir principalement la apostrophe et le caractère > par leur représentation alternative :

<HTML>
<HEAD></HEAD>
<BODY>
<form action='result.php' method='post'>
<input type='text' name='MAVAR_ENSORTIE' value=<?php echo ereg_replace(&#62;CHR(62),"&#62",ereg_replace(CHR(39),"&#39",$MAVAR)) ?> >
</BODY> </HTML>

Si l'on consulte le source du fichier envoyé par PHP au navigateur, on verra maintenant :

<input type='text' name='MAVAR_ENSORTIE' value='Ceci est la page de Stéph&#39 - Bonjour ! '>

Pour le navigateur, la seconde apostrophe n'apparait bien qu'après le "Bonjour !", il prend bien toute la chaine en tant que valeur. Et au moment de l'affichage de cette valeur dans la zone de saisie il remplace le code "&#39" par une apostrophe.

Fatal error: Unable to open C:\Mes in - on line 0 No input file specified.

Une erreur assez classique qui se produit avec certaines versions de PHP et/ou avec certains serveurs. Dans le cas présent le script tente d'accéder à un répertoire dont le nom contient des espaces ("Mes Documents"). Ce qui n'est pas apprécié par certains serveurs, notemmemt les serveurs Unix. Ceci est également valable pour les noms de fichiers. Une bonne habitude pour s'éviter ces désagréments consiste donc à n'utiliser que des noms de répertoires ou fichiers exempts d'espaces, de caractères accentués, et typographiés en minuscules uniquement.

Fatal error: Unable to open c:\datas\htdocs\html\php\test.php3 in - on line 0 No input file specified.

Une erreur toute bête mais le message n'est pas forcement clair, surtout quand il indique une erreur à la ligne 0. En fait c'est tout simplement que le fichier indiqué n'existe pas et qu'il y a donc une erreur de frappe soit dans son chemin d'accès soit dans son nom.

Commentaires

Aucun commentaire. Soyez le premier !

Pseudo
Email
Commentaire

Merci d'écrire le code ici :