question bête sur condition preg_match_all

Eléphant du PHP | 73 Messages

24 mai 2011, 15:55

bonjour,

j'ai un petit soucis sur une de mes fonctions et j'ai du mal à voir ce qui cloche.

j'ai un champ par exemple : U36U38
j'ai une fonction qui vérifie que ce champ est bien au format UXXUXX, ce qui fonctionne très bien.

mon soucis : je viens de rajouter une condition dans cette fonction qui doit m'autoriser à mettre ce champ à "NO", donc j'ai le droit soit à un champ au format UXXUXX, soit à NO.

hors, la condition pour le "NO" ne fonctionne pas.

voici la fonction :
function VerifyBaieloc($champ) {
  if(!preg_match_all('/^[U-Uu-u][0-9][0-9][U-Uu-u][0-9][0-9]$/', $champ, $out) || !preg_match_all('/^[n-N][o-O]$/', $champ, $out)){
   echo '<br><br><font face="verdana">Erreur: la valeur "Emplacement dans la baie" doit etre au format UXXUXX</font><br><br>';
   echo '<a href="javascript:history.back()"><font face="verdana" color="#91aa37">Retourner en arriere<br></a>';
   exit;
 }
}
malgré mon champ mis à "NO", je me tape une erreur "Erreur: la valeur "Emplacement dans la baie" doit etre au format UXXUXX". alors que cela devrait fonctionner et ne pas m'afficher d'erreur, qu'ai-je fait de pas bien dans mon "|| !preg_match_all('/^[n-N][o-O]$/', $champ, $out)" ?

merci !

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

24 mai 2011, 18:28

Le problème vient de ton || (OU). En effet, ton if test si ta chaine ne respecte pas ton masque OU si ta chaine ne respecte pas le masque NO. Mais si ta chaine est égale à "NO", elle ne respecte pas le premier test. Et puisque c'est l'un OU l'autre et que le premier est vrai, il rentre dans le if.

Code : Tout sélectionner

!(A OU B) <=> !A ET !B
A noter par ailleurs que tu peux grandement optimiser ton code en testant si la chaine est égale à "NO" (sans passer par une expression régulière). Tu peux également optimiser tes masques en utilisant l'option "i" pour rendre l'expression insensible à la casse :
strToUpper($champ)=='NO'

/^[U-Uu-u][0-9][0-9][U-Uu-u][0-9][0-9]$/
/^U[0-9][0-9]U[0-9][0-9]$/i
/^U[0-9]{2}U[0-9]{2}$/i
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Invité
Invité n'ayant pas de compte PHPfrance

25 mai 2011, 10:14

ah, pas bête pour les expressions régulières, merci beaucoup je n'y avais pas pensé.

sinon merci pour l'explication sur ma condition, mais quelle serait donc la meilleure solution ? je dois mettre un truc du genre :

if (!condition1) || (!condition2)

à la place de

if (!condition1 || !condition2) ?

merci pour ta réponse encore

Eléphant du PHP | 73 Messages

25 mai 2011, 10:28

j'ai testé plusieurs choses et rien ne fonctionne :(

comme :

if ( ! condition1 || condition2 )
if ( !condition1 || !condition2 )
if ( (!condition1) || (!condition2) )
if ( !condition1 ) || ( !condition2 )

doit y avoir un truc que je n'ai pas saisi :)

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

25 mai 2011, 10:45

Ton test est vrai si :
- ta chaine respecte le masque OU que ta chaine est égale à "NO".

Par conséquent ton test est faux et doit déclencher un message d'erreur si
- ta chaine ne respecte pas le masque ET que ta chaine n'est pas égale à "NO"

;)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 73 Messages

25 mai 2011, 11:21

merci.

en fait, dans ma logique, ma fonction résonne comme ça :

SI (le champ n'est PAS au bon format UxxUxx OU que le champ n'est PAS egal à NO) {
alors : on affiche une erreur
}

ce qui donne "dans ma logique" :

SI ( champ!format_UxxUxx || champ!format_NO ) {
erreur
}

en gros : "si le champ n'est pas du format de l'un ou l'autre, alors erreur", ce qui implique que le champ doit être soit d'un format soit de l'autre)

j'imagine que ma compréhension du "OU" n'est pas bonne en effet :)

quand je code de la même façon en bash, ça fonctionne très bien, mais j'ai du mal à comprendre pourquoi cela fonctionne différemment en php :p
en bash quand je fait un :

if [ champ ! cond1 ] || [ champ ! cond2 ]
then
error
fi

ça marche tb :)

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

25 mai 2011, 13:20

Mes cours de shell remontent à loin, mais ça m'étonne qu'il y ait une différence de comportement...

En fait, pour entrer dans le if(), il faut que l'une ou l'autre des conditions soit vérifiée. php va donc commencer par regarder si la première condition est vérifiée. Vu que la valeur "NO" ne respecte pas ce masque, le test est vrai. php n'a donc pas besoin d'aller vérifier la seconde condition puisque la première est vérifiée et suffisante pour entrer dans le if().
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

25 mai 2011, 13:40

salut,

pourquoi preg_match_all ? le motif indique clairement une seule occurrence donc preg_match devrait suffire.

ensuite c'est bien soit la chaine correspond au motif soit elle est égale à NO ?
dans ce cas
if (preg_match('/^[U-Uu-u][0-9][0-9][U-Uu-u][0-9][0-9]$/',$champ) || strToUpper($champ)=='NO') devrait fonctionner

exemple en logique "positive"
<?php
 function VerifyBaieLoc($champ){
	if (preg_match('/^[U-Uu-u][0-9][0-9][U-Uu-u][0-9][0-9]$/',$champ) || strToUpper($champ)=='NO'){ 
		echo $champ,' : bon';
	}
	else {
		echo $champ,' : ko';
	}
}
?>
avec la négation
<?php
function VerifyBaieLoc($champ){
	if (!preg_match('/^[U-Uu-u][0-9][0-9][U-Uu-u][0-9][0-9]$/',$champ) && strToUpper($champ)!='NO'){ 
		echo 'pas bon'; 
	} 
	else { 
		echo 'ok';
	}
}
?>
@+
Il en faut peu pour être heureux ......