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 > 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(>CHR(62),">",ereg_replace(CHR(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' - 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 "'" 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.
Aucun commentaire:
Enregistrer un commentaire