2009-04-02 14 views
2

J'ai une question intéressante sur la façon dont PHP évalue les expressions booléennes. Lorsque vous avez, par exemple,Comment puis-je éviter PHP éviter évaluation paresseux?

$expression = $expression1 and $expression2; 

ou

if ($expression1 and $expression2) 

PHP vérifie d'abord si $expression1 est évaluée à true. Si ce n'est pas le cas, alors $expression2 est simplement ignoré pour éviter des calculs inutiles. Dans un scénario que je vous écris, j'ai:

if ($validator->valid("title") and $validator->valid("text")) 

je dois avoir la deuxième déclaration ($validator->valid("text")) évaluée, même si la première est évaluée à false. Je voudrais vous demander s'il existe un moyen facile de forcer PHP à toujours évaluer les deux instructions. Je vous remercie!

Répondre

11

Ceci est connu comme short circuit evaluation, et pour l'éviter, vous devez le faire, en utilisant un seul &:

if($validator->valid("title") & $validator->valid("text")) { 

} 

Notez que ce n'utilise pas logical operators mais en fait bitwise operators:

Ce sont des opérateurs qui agissent sur les représentations binaires des nombres. Ils ne prennent pas de valeurs logiques (c'est-à-dire, "vrai" ou "faux") comme arguments sans les convertir d'abord aux nombres 1 et 0 respectivement. Ils ne renvoient pas non plus de valeurs logiques, mais des nombres. Bien sûr, vous pouvez traiter ces nombres comme s'ils étaient des valeurs logiques (dans ce cas, 0 est converti en "false" et tout le reste est "true"), mais c'est une conséquence des règles de cast de PHP, et rien à faire avec le comportement des opérateurs.

En tant que tel, il y a un débat de savoir s'il est bon d'utiliser cet effet secondaire pour contourner l'évaluation de court-circuit. Je voudrais personnellement au moins mettre un commentaire que le & est intentionnel, mais si vous voulez être aussi pur que possible, vous devriez évaluer si elles sont d'abord valides, puis faites le si.

+3

C'est très imprudent. Que faire si le premier renvoie vrai, et le dernier renvoie 2. vrai et 2 font faux! De plus, un responsable viendra probablement dire "whoops, ça devrait être &&, pas &", en brisant le code. http://stackoverflow.com/questions/710919/how-can-i-have-php-avoid-lazy-evaluation/710936#710936 est une réponse beaucoup plus sûre et plus claire. –

+1

Je suis parfaitement au courant des limitations, avez-vous même lu ma réponse? –

+0

@Paolo Bergantino: Je l'ai fait. Je voulais souligner que cela ne devrait pas être choisi comme la bonne réponse, aussi intelligent soit-il (enfin, c'est vraiment trop intelligent). –

26
$isValidTitle = $validator->valid("title"); 
$isValidText = $validator->valid("text"); 
if($isValidTitle && $isValidText) 
{ 
    ... 
} 

Est-ce que ça va?

+7

J'aime cette solution car il est explicitement indiqué que les méthodes devraient être exécutées en code, pas en tant que simple test. Il y a des écoles de pensée qui croient que les déclarations avec des effets secondaires ne devraient jamais entrer dans des déclarations de contrôle - les déclarations de contrôle ne sont que pour tester, ne jamais exécuter. –

3

Cela pourrait ne pas être la meilleure mise en œuvre, mais vous pouvez toujours faire:

$a=$validator->valid("title"); 
$b=$validator->valid("text"); 
if($a && $b) {...} 
4

essayer d'évaluer chaque terme séparément:

$term1 = $validator->valid("title"); 
$term2 = $validator->valid("text"); 
if($term1 && $term2) { 
//things to do 
} 
0

Alternativement, si vous pouvez modifier le validateur classe $ instancier, vous pourriez faire la méthode valide accepter une chaîne ou un tableau. Si c'est un tableau, il exécute le code qui existe déjà sur chaque élément et ne renvoie VRAI que si tous les éléments sont "valides".

1

Vous pouvez définir une fonction comme:

function logical_and($x,$y) {return ($x && $y);} 

Depuis PHP utilise l'appel par valeur, cela fonctionne.