2011-01-26 14 views
5

Sono abbastanza in grado di utilizzare l'operatore ternario PHP. Tuttavia, ho trovato un ostacolo nel tentativo di capire perché il codice sottostante non corrisponde alla struttura equivalente if else. Il test è stato eseguito tre volte su numeri diversi. L'output per ogni struttura è inferiore al codice.Problema ternario php nidificato: output ternario! = If - else

ternario:

$decimal_places = ($max <= 1) ? 2 : ($max > 3) ? 0 : 1; 

uscita ternario:

max: -100.000 decimali: 0

max: 0.48 decimali: 0

max: 0.15 decimali: 0

if-else

if($max <= 1) 
$decimal_places = 2; 
elseif($max > 3) 
$decimal_places = 0; 
else 
$decimal_places = 1; 

if-else uscita:

max: decimale -100.000: 2

max: 0,48 decimali: 2

max: 0.15 decimali: 2

Qualcuno può dirmi per favore perché questi due controlli le strutture non producono gli stessi dati?

+4

Una ragione per cui non è una buona idea nidificare gli operatori ternari –

+1

Non sono equivalenti esatti, lo sai. L'intero resto andrà in cortocircuito nella struttura ternaria. Inoltre non sono pensati per essere annidati. –

+1

[dal manuale PHP sugli operatori ternari] (http://de3.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary): Si consiglia di evitare "l'impilamento" "espressioni ternarie. Il comportamento di PHP quando si utilizza più di un operatore ternario all'interno di una singola istruzione non è ovvio – Gordon

risposta

18

Il diritto-mano-lato di espressione ternaria ha bisogno di essere avvolto in parentesi così sarà valutata da solo come una sola espressione:

$decimal_places = ($max <= 1) ? 2 : (($max > 3) ? 0 : 1); 

// Another way of looking at it 
$decimal_places = ($max <= 1) 
       ? 2 
       : (($max > 3) ? 0 : 1); 

Altrimenti la vostra espressione ternaria viene valutata da sinistra a destra, con conseguente:

$decimal_places = (($max <= 1) ? 2 : ($max > 3)) ? 0 : 1; 

// Another way of looking at it 
$decimal_places = (($max <= 1) ? 2 : ($max > 3)) 
       ? 0 
       : 1; 

il che, tradotto in if-else, diventa questo:

if ($max <= 1) 
    $cond = 2; 
else 
    $cond = ($max > 3); 

if ($cond) 
    $decimal_places = 0; 
else 
    $decimal_places = 1; 

Pertanto $decimal_places finisce come 0 per tutti i valori di $max eccezione 2, nel qual caso esso risolve a 1.

2

Il codice viene eseguito come

$decimal_places = (($max <= 1) ? 2 : ($max > 3)) ? 0 : 1; 

in modo non avrete mai 2 e 1 solo quando 1 < $max <=3. Questo perché l'operatore condizionale è left-associative. Soluzione: Posizionare parentesi per assicurarsi che l'ordine che si desidera è codificato:

$decimal_places = ($max <= 1) ? 2 : (($max > 3) ? 0 : 1); 
1

Basta mettere la parentesi e si sarebbe bene, come questo:

$decimal_places = ($max <= 1) ? 2 : (($max > 3) ? 0 : 1); 
1

Come altri hanno sottolineato, utilizzare paranthesis.
Tuttavia, se si vuole realmente renderlo leggibile, che dire di questo:

$decimal_places = 
    ($max <= 1) ? 2 : (
    ($max > 3) ? 0 : (
    1 
)); 

questo sembra ancora super imbarazzante, ma questo disagio ha una forma regolare, quindi è più facile vivere con.

$drink = 'wine'; 
return 
    ($drink === 'wine') ? 'vinyard' : (
    ($drink === 'beer') ? 'brewery' : (
    ($drink === 'juice') ? 'apple tree' : (
    ($drink === 'coffee') ? 'coffeebeans' : (
    'other' 
)))); 

Si potrebbe naturalmente omettere l'ultima coppia di staffe, ma che renderebbe meno regolare di aspetto.

+0

Davvero imbarazzante, ma ho ancora capito che è bello per me (perché ho un sacco di controlli se le istruzioni all'interno degli switch ecc ...) – FreshPro