I was running some unit tests and ran across an unexpected behavior with a switch statement I was using. I've isolated the condition below.
function test($val)
{
switch($val)
{
case 'a':
case 'b':
return 'first';
break;
case 'c':
return 'second';
break;
default:
return 'third';
}
}
here are my first round of tests:
test('a') => 'first'
test('b') => 'first'
test('c') => 'second'
test('d') => 'third'
test('0') => 'third'
test('1') => 'third'
test('true') => 'third'
test('false') => 'third'
This is pretty self evident right? ok now check these out:
test(0) => 'first' // expected 'third'
test(1) => 'third'
test(true) => 'first' // expected 'third'
test(false) => 'third'
test(null) => 'third'
test([]) => 'third'
What's with the weird results with 0 and true? I would chalk it up to loose typing if 1/true and 0/false returned the same values. But they don't!
If I convert the value to a (string) then the switch works as intended.
test((string) 0) => 'third'
test((string) 1) => 'third'
test((string) true) => 'third'
test((string) false) => 'third'
I don't understand why the switch wont "work" as I intended without using "(string)"
Can someone explain why this is happening?
This is expected behavior. When doing comparisons, PHP will alter a value's type in its search for a match.
test(0) => 'first' // 'a' is altered into int 0 and therefore matches
var_dump((int) 'a'); // results 'int(0)'
test(true) => 'first' // both true and 'a' are truthy statements therefore matches.
if ('a' == true) echo "its true";
PHP is a weakly typed language and that bites you in the butt sometimes. You may consider re-factoring the switch into an if/else if/else structure and use the ===
operator for strong comparisons.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With