2010-12-01 14 views
18

Für den sehr häufigen Fall eines Wertes einer Variablen zugewiesen, basierend auf dem Ergebnis eines Ausdrucks ich ein Fan von ternären Operatoren bin:Bedingte Zuweisung PHP-Werte

$foo = $bar ? $a : b; 

Wenn jedoch $ bar ein relativ ist teure Operation, und ich möchte das Ergebnis von $ bar zu $ ​​foo zuweisen, wenn das Ergebnis truthy ist, ist dies ineffizient:

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

Eine Option ist:

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

Aber ich würde lieber nicht die extra $result im Speicher sitzen haben.

Die beste Option, die ich habe ist:

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

Oder ohne ternären Operatoren:

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

Oder, wenn Programmablauf Betreiber sind nicht Ihr Stil:

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

So viele Optionen, keine davon wirklich zufriedenstellend. Was würdest du benutzen, und mir fehlt hier etwas wirklich Offensichtliches?

Antwort

33

PHP 5.3 hat eine neue Syntax genau dieses Problem zu lösen:

$x = expensive() ?: $default; 

Siehe documentation:

Seit PHP 5.3 ist es möglich, den mittleren Teil des ternären Operator auszulassen .
Ausdruck expr1 ?: expr3 gibt expr1 zurück, wenn expr1TRUE und expr3 andernfalls ergibt.

+1

Ich vermeide persönlich PHP 5.3-only-Syntax , und bevorzuge '$ x = teuer(); ob (!$ x) $ x = $ default; ' – meagar

+0

Wow; Ich wollte nur kommentieren mit "PHP benötigt die [GNU-Erweiterung für ternaries] (http://stackoverflow.com/questions/3319075/ternary-conditional-operator-behaviour-when-leaving-one-expression-empty)" –

+0

ah ha - das habe ich im Handbuch verpasst. Ich nehme an, dass es keine bessere Methode für 5.2.x gibt (die ich mittelfristig unterstützen muss)? – Hamish

8

Können Sie SomeClass aktualisieren: bigQuery(), um ein neues EmptySet() anstelle von false zurückzugeben?

Dann einfach Sie haben

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

+1 für Cleaner Code. – Jonah

+0

Das wäre eigentlich meine Vorliebe - leider baue ich oben auf einer Bibliothek, die diesen Fehler von Tag-0 gemacht hat und jetzt haben sie zu viel Zeug hängen von der API, um es zu beheben:/ – Hamish

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

Revision zwei, Kredit @meagar

+0

Es ist ärgerlich ausführlich, ich persönlich bevorzuge die anderen antworten. –

+0

Realisierte eine Möglichkeit, Ausführlichkeit zu reduzieren. – Jonah

+0

Warum nicht? If (! $ Foo) $ foo = new EmptySet(); '? Etwas weniger foo's. – meagar

1

Eine leichte Variation der letzten Option:

$ foo = Someclass :: BigQuery() oder neues EmptySet(); das funktioniert eigentlich nicht, danke fürs merken.

häufig in Kombination mit mySQL-Code, aber scheint immer in vergleichbaren Situationen vergessen:

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

Obwohl ich persönlich vorziehen Sie bereits erwähnt:

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

ah, du hast recht das ist immer vergessen. Nett! – Hamish

+0

Eigentlich muss das lesen: '$ foo = SomeClass :: bigQuery() oder $ foo = new EmptySet();' was entspricht der 3. Option. – Hamish