Unexpected results of integer to string comparisons

If you want to make a php programmer applicant cry, give them this bit of code and ask them to predict the output.

<?php
 
$value
= 0;
switch (
$value) {
  case
'some specific string':
    print
"I'm the specific string.";
    break;
   
  case
0:
    print
"I'm zero duh!!";
    break;
 
  default:
    print
"I'm default";
    break;
}
?>

Seems super easy to predict, but most get it wrong.
The answer is I'm the specific string.!?!?

The confusion comes from an oddity in php's handling of loose integer to string comparisons. Here is a closer look:

<?php
// integer to integer all make sense.
0 == 0       // TRUE
0 == 1      // FALSE
0 == 500  // FALSE

// integer to boolean make sense.
0 ==  FALSE  //  TRUE
0 ==  TRUE   //  FALSE
0 == NULL   // TRUE

// integer to string that look like numbers make sense.
0 == '0'  // TRUE
0 == '1' // FALSE
0 == '500' // FALSE
0 == '-1'  //FALSE

// integer to strings that don't look like numbers
0 == ''  //  TRUE
// So far so good.  Now the madness begins.
0 == 'Some specific string that is not a number.'  // TRUE   !?!?!?
?>

Source: http://php.net/manual/en/types.comparisons.php#types.comparisions-loose

There is probably some deep reason why 0 == 'string' should be TRUE, but I can't think of it. Coding purists will say you should never do loose comparisons on variables that have not been cast. They are probably right. Switch cases can be nice to use, but they force you into loose comparisons.. ALMOST.

A 'switch race' is a way to make the switch cases be as loose or strict as you want to write them. This is done by having the switch actually be TRUE or FALSE and the first case to evaluate to that, wins the race.

<?php
 
// Switch race.  First to evaluate TRUE wins.
switch (TRUE) {
  case (
$value === 'some specific string'):
    print
"I'm the specific string.";
    break;
   
  case (
$value === 0):
  case (
$value == 0):
    print
"I'm zero duh!!";
    break;
 
  default:
    print
"I'm default";
    break;
}
?>

There are a couple uses where the 'switch race' is better than a bunch of if.. elseifs. Example: When you need to have some of the items cascade by not having each case have a break.

section: