Not seeing any explanation about why your code is broken in the other answers, so here is a quick run-down.
The problem here is made more obvious is you add brackets to make the implicit order of evaluation more explicit.
Here's a trimmed down version of your code, which still produces the incorrect result of "horse":
$t = 'T';
( $t == 'T' ) ? 'train' :
( $t == 'C' ) ? 'car' :
( $t == 'H' ) ? 'horse' : 'feet';
First, lets unroll it:
( $t == 'T' ) ? 'train' : ( $t == 'C' ) ? 'car' : ( $t == 'H' ) ? 'horse' : 'feet';
Next, I'll add explicit parenthesis where there are already implicit ones:
((($t == 'T') ? 'train' : ($t == 'C')) ? 'car' : ($t == 'H')) ? 'horse' : 'feet';
Next, we can resolve your comparisons:
((true ? 'train' : false) ? 'car' : false) ? 'horse' : 'feet';
You should start to see why this is broken. The first ternary evaluates true ? 'train' : 'false'
to 'train'
:
('train' ? 'car' : false) ? 'horse' : 'feet';
Because 'train'
is true when cast to a boolean, the result is now 'car'
:
'car' ? 'horse' : 'feet';
Again, because a non-empty string is "true", the result is now 'horse'. So, the first time a true
comes up in your horrible nested case statement, the result will cascade through all remaining statements, throwing out the previous value for the "true" branch of the next operator.
The solution is to avoid this code. It is an attempt to be far, far too clever, and the result is a broken, unreadable mess. There is absolutely no reason to use it. Choose a switch
statement, it's purpose built for exactly what you're trying to do.