28

I use ternary operators alot but I can't seem to stack multiple ternary operator inside each other.

I am aware that stacking multiple ternary operator would make the code less readable but in some case I would like to do it.

This is what I've tried so far :

$foo = 1;
$bar = ( $foo == 1 ) ? "1" : ( $foo == 2 ) ? "2" : "other";
echo $bar; // display 2 instead of 1

What is the correct syntax ?

Cybrix
  • 3,248
  • 5
  • 42
  • 61

8 Answers8

68

Those parenthesis are what I think is getting you.

Try

$foo = 1;
$bar = ($foo == 1) ? "1" : (($foo == 2)  ? "2" : "other");
echo $bar;
Brandon Horsley
  • 7,956
  • 1
  • 29
  • 28
26

The problem is that PHP, unlike all other languages, makes the conditional operator left associative. This breaks your code – which would be fine in other languages.

You need to use parentheses:

$bar = $foo == 1 ? "1" : ($foo == 2 ? "2" : "other");

(Notice that I’ve removed the other parentheses from your code; but these were correct, just redundant.)

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 1
    "_Notice that I’ve removed the other parentheses from your code; but these were correct, just redundant_" - but with a parser like that, you can never be sure... ;-) – Alnitak Jun 01 '11 at 15:06
12

You need some parentheses around the right hand operand:

$foo = 1;
$bar = ( $foo == 1 ) ? "1" : (( $foo == 2 ) ? "2" : "other");
echo $bar;

PHP's interpreter is broken, and treats your line:

$bar = ( $foo == 1 ) ? "1" : ( $foo == 2 ) ? "2" : "other";

as

$bar = (( $foo == 1) ? "1" : ( $foo == 2)) ? "2" : "other";

and since that left hand expression evaluates as "true" the first operand of the remaining ternary operator ("2") is returned instead.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • -1 Broken? The parser behaves exactly as defined by PHPs operator precedence and associativity overview: http://php.net/manual/en/language.operators.precedence.php – NikiC Jun 01 '11 at 15:24
  • 3
    @nikic PHP's manual documented the implementation - the documents don't _define_ the implementation, as PHP never had a formal specification. The implementation is broken (i.e. different) when compared to every other language that supports the ternary operator. – Alnitak Jun 01 '11 at 16:16
  • If you meant to say that it was different to what you are used to, why not say just that? – NikiC Jun 01 '11 at 17:05
  • 5
    @nikic I said exactly what I meant to say. Any sane language "design" would have followed the precedent set by C, C++, Java, etc. – Alnitak Jun 01 '11 at 17:13
4

Put parenthesis around each inner ternary operator, this way operator priority is assured:

$bar = ( $foo == 1 ) ? "1" : (( $foo == 2 ) ? "2" : "other");
faken
  • 6,572
  • 4
  • 27
  • 28
4

You could write this correctly thus:

$bar = ($foo == 1) ? "1" : (($foo == 2) ? "2" : "other");

(i.e.: Simply embed the 'inner' ternary operator in parenthesis.)

However, I'd be really tempted not to do this, as it's about as readable as a particularly illegible thing that's been badly smudged - there's never any excuse for obfuscating code, and this borders on it.

John Parker
  • 54,048
  • 11
  • 129
  • 129
4

Just stack up the parenthesis, and you've got it:

$bar = ($foo==1? "1" : ($foo==2? "2" : "other"));

As an aside, if you've got many clauses, you should consider using a switch:

switch ( $bar ) {
  case 1:  echo "1";
  case 2:  echo "2";
  default: echo "other";
}

If the switch gets long, you can wrap it in a function.

csl
  • 10,937
  • 5
  • 57
  • 89
  • This is a good example of why the `switch` statement is flawed. This example does not have any `break;` lines, so `"2"` will unintentionally be echoed for `case 1`. – Dem Pilafian Feb 13 '23 at 10:22
3
$foo = 1;
$bar = ( $foo == 1 ) ? "1" : (( $foo == 2 ) ? "2" : "other");
echo $bar;

Just use extra ( ) and it will work

Serg
  • 668
  • 1
  • 4
  • 6
2

Add the parenthesis:

$bar = ( $foo == 1 ) ? "1" : (( $foo == 2 ) ? "2" : "other");
Yuri Stuken
  • 12,820
  • 1
  • 26
  • 23