1

I've got nested ternary operators in my code like this:

$error = $fault_all ? "ALL" : $fault_twothirds ? "TWOTHIRDS" : $fault_onethird ? "ONETHIRD" : "UNKNOWN";
        echo 'STATEERROR: ' . $error . ';';

They are listed in order of my preference left to right so if $fault_all and $fault_twothirds are true, I want "ALL" to be assigned to $error; The same if all of them are true. If all are false "UNKNOWN" should be assigned to error.

However, if any of them are true only "ONETHIRD" is returned, if all false "UNKNOWN" is returned. How do I make the "ALL" and "TWOTHIRDS" to be returned?

5
  • 7
    Nested ternary operators are unfriendly to debug. Don't use them. Switch to if/else/etc instead. Commented Apr 16, 2012 at 11:42
  • 4
    PHP acts differently with nested ternary operators than any other language. See here Commented Apr 16, 2012 at 11:42
  • 2
    use paranthesis for deciding priority Commented Apr 16, 2012 at 11:45
  • OK, thank you. I'm going to use ifs/elses instead. Commented Apr 16, 2012 at 11:49
  • Dan Lee - thank you for pointing me to this quirk. Commented Apr 16, 2012 at 11:50

3 Answers 3

2

I suggest you use ( and ) to separate the different ternaries from eachother, or use if/else clauses.

Sign up to request clarification or add additional context in comments.

2 Comments

Could be, although I'm not a fan of that. But that's just taste :)
Fair enough, although switching booleans is very useful when you have whole bunch of operations that all return something that evaluates to TRUE, and you want to break the procedure and handle with an error when one of them fails, or vice versa. case <expr>: is a very useful/powerful construct when used correctly, although (much like goto) it should only be used by people who understand the implications of it...
1

In terms of being able to debug and manage a list of states, I would recommend stopping usage of a ternary, which is unreadable, and use a switch, an if-elseif statement, or, if you anticipate a long list, an approach as follows:

<?php
function state( $states ) {
    foreach( $states as $state => $current ) {
        if( $current ) {
            return $state;
        }
    }
    return 'UNKNOWN';
}

$states = array(
    'ALL' => $fault_all,
    'TWOTHIRDS' => $fault_twothirds,
    'ONETHIRD' => $fault_onethird
);

var_dump( state( $states ) );

That said, this should work, I think:

<?php
$error = ( $fault_all ? "ALL" : ( $fault_twothirds ? "TWOTHIRDS" : ( $fault_onethird ? "ONETHIRD"  : "UNKNOWN" ) ) );

1 Comment

Thank you, and your nested ternaries do work indeed !! I tried using parentheses myself but I nested them incorrectly.
1

This is a known issue. -- veekun

Take for instance the following nested ternary ...

<?php 
$arg = 'T';
$vehicle = ( ( $arg == 'B' ) ? 'bus' :
           ( $arg == 'A' ) ? 'airplane' :
           ( $arg == 'T' ) ? 'train' :
           ( $arg == 'C' ) ? 'car' :
           ( $arg == 'H' ) ? 'horse' :
           'feet' );
echo $vehicle; 

prints 'horse'

As @berry-langerak stated use a control flow function ...

Using an object {array, structure} is much more reliable ... I.E.

$vehicle = (empty( $vehicle) ?

    array(

    'B' => 'Bus',
    'A' => 'Airplane',
    'T' => 'Train',
    'C' => 'Car',
    'H' => 'Horse',

    ):

    NULL
 );

 $arg = 'T';

 $vehicle = (! empty($arg) ? $vehicle[$arg] : "You have to define a vehicle type");

 echo($vehicle);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.