2010-12-01 14 views
18

Para el caso muy común de asignar un valor a una variable en función del resultado de una expresión que soy un fan de los operadores ternarios:condicionalmente la asignación de valores de PHP

$foo = $bar ? $a : b; 

Sin embargo, si $ bar es relativamente operación costosa y quiero asignar el resultado de la barra de $ a $ foo si el resultado es Truthy, esto es ineficiente:

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

Una opción es:

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

Pero prefiero no tener el $result extra en la memoria.

La mejor opción que tengo es:

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

O, sin operadores ternarios:

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

O, si los operadores de flujo del programa no son su estilo:

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

Tantas opciones, ninguna de ellas realmente satisfactoria. ¿Cuál usarías, y me estoy perdiendo algo realmente obvio aquí?

Respuesta

33

PHP 5.3 introdujo una nueva sintaxis para resolver exactamente este problema:

$x = expensive() ?: $default; 

Véase el documentation:

A partir de PHP 5.3, es posible dejar de lado la parte media del operador ternario .
Expresión expr1 ?: expr3 devuelve expr1 si expr1 evalúa a TRUE, y expr3 en caso contrario.

+1

yo personalmente evitar PHP 5.3 sólo sintaxis , y prefiere '$ x = caro(); Si (!$ x) $ x = $ predeterminado; ' – meagar

+0

Wow; Solo iba a comentar con "PHP necesita la [extensión de GNU para ternaries] (http://stackoverflow.com/questions/3319075/ternary-conditional-operator-behaviour-would-leaving-one-expression-empty)" –

+0

ah ha - lo perdí en el manual. Supongo que eso significa que no hay un mejor método para 5.2.x (que tengo que apoyar en el mediano plazo)? – Hamish

8

¿Se puede actualizar SomeClass: bigQuery() para devolver un nuevo EmptySet() en lugar de falso?

A continuación, sólo tiene

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

+1 para un código más limpio. – Jonah

+0

Esa sería mi preferencia, desafortunadamente estoy construyendo sobre una biblioteca que cometió este error desde el día 0 y ahora tienen demasiadas cosas colgando de la API para arreglarlo:/ – Hamish

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

Revisión dos, de crédito @meagar

+0

Es molestamente prolijo, yo personalmente prefiero las otras respuestas. –

+0

Se dio cuenta de una forma de reducir la verbosidad. – Jonah

+0

¿Por qué no 'if (! $ Foo) $ foo = new EmptySet();'? Un poco menos de Foo. – meagar

1

Una ligera variación de su última opción:

$ foo = SomeClass :: bigquery() o nuevo EmptySet(); Esto realmente no funciona, gracias por notarlo.

utiliza a menudo en combinación con el código de MySQL, pero parece siempre olvidados en situaciones comparables:

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

Aunque personalmente prefiero uno ya lo ha dicho:

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

ah, tienes razón de que siempre se olvida. ¡Bonito! – Hamish

+0

En realidad, eso necesita leer: '$ foo = SomeClass :: bigQuery() o $ foo = new EmptySet();' que es equivalente a la tercera opción. – Hamish

Cuestiones relacionadas