2010-12-01 11 views
18

Pour le cas très fréquent d'attribuer une valeur à une variable en fonction du résultat d'une expression que je suis un fan des opérateurs ternaires:conditionnellement attribuer des valeurs PHP

$foo = $bar ? $a : b; 

Cependant, si la barre de $ est relativement opération coûteuse et je veux affecter le résultat de la barre de $ à $ foo si le résultat est truthy, cela est inefficace:

$foo = SomeClass::bigQuery() ? SomeClass::bigQuery() : new EmptySet(); 

Une option est:

$foo = ($result = SomeClass::bigQuery()) ? $result : new EmptySet(); 

Mais je préfère ne pas avoir le $result supplémentaire en mémoire.

La meilleure option que j'ai est:

$foo = ($foo = SomeClass::bigQuery()) ? $foo : new EmptySet(); 

Ou, sans opérateurs ternaires:

if(!$foo = SomeClass::bigQuery()) $foo = new EmptySet(); 

Ou, si les opérateurs de flux de programme ne sont pas votre style:

($foo = SomeClass::bigQuery()) || ($foo = new EmptySet()); 

Autant d'options, pas vraiment satisfaisantes. Lequel utiliseriez-vous, et est-ce que je manque quelque chose de vraiment évident ici?

Répondre

33

PHP 5.3 introduit une nouvelle syntaxe pour résoudre exactement ce problème:

$x = expensive() ?: $default; 

Voir la documentation:

Depuis PHP 5.3, il est possible de quitter la partie centrale de l'opérateur ternaire .
L'expression expr1 ?: expr3 renvoie expr1 si expr1 est évaluée à TRUE et expr3 dans le cas contraire.

+1

J'évite personnellement PHP syntaxe 5.3 uniquement , et préfèrent '$ x = cher(); si (!$ x) $ x = $ par défaut; ' – meagar

+0

Wow; J'allais juste commenter avec "PHP a besoin de l'extension [GNU pour ternaries] (http://stackoverflow.com/questions/3319075/ternary-conditional-operator-behaviour-when-leaving-one-expression-empty)" –

+0

ah ha - manqué que dans le manuel. Je suppose que cela signifie qu'il n'y a pas de meilleure méthode pour 5.2.x (que je dois soutenir à moyen terme)? – Hamish

8

Pouvez-vous mettre à jour SomeClass: bigQuery() pour retourner un nouvel EmptySet() au lieu de false?

Il vous suffit

$foo = SomeClass::bigQuery(); 
+0

+1 pour le code plus propre. – Jonah

+0

Ce serait en fait ma préférence - malheureusement, je construis sur une bibliothèque qui a fait cette erreur depuis le jour 0 et maintenant ils ont trop de choses qui pendent de l'API pour le réparer:/ – Hamish

1
$foo = SomeClass::bigQuery(); 
if (!$foo) $foo = new EmptySet(); 

Révision deux, crédit @meagar

+0

Il est ennuyeux verbeux, je préfère personnellement les autres réponses. –

+0

Réalisé un moyen de réduire la verbosité. – Jonah

+0

Pourquoi pas 'if (! $ Foo) $ foo = new EmptySet();'? Un peu moins de foo. – meagar

1

Une légère variation de votre dernière option:

$ foo = SomeClass :: BigQuery() ou nouveau EmptySet(); cela ne fonctionne pas réellement, merci de le remarquer.

Utilisé souvent en combinaison avec le code mySQL, mais semble toujours oublié dans des situations comparables:

$result = mysql_query($sql) or die(mysql_error()); 

Bien que je préfère que vous l'avez mentionné:

if(!$foo = SomeClass::bigQuery()) 
    $foo = new EmptySet(); 
+0

ah, vous avez raison qui est toujours oublié. Agréable! – Hamish

+0

En fait, cela doit être lu: '$ foo = SomeClass :: bigQuery() ou $ foo = new EmptySet();' qui est équivalent à la 3ème option. – Hamish