DEV Community

Jimmy Klein
Jimmy Klein

Posted on

Be careful about the switch statement in PHP

Could you find the difference in results between these two codes?

function getStatusByCode($code)
{   
    $status = '';

    switch ($code) {
        case 0:
            $status = 'OK';
            break;

        case 1: 
            $status = 'WARNING';
            break;

        default:
            $status = 'UNDEFINED';
            break;
    }    

    return $status;
}

var_dump(getStatusByCode(null));
Enter fullscreen mode Exit fullscreen mode

and

function getStatusByCode($code)
{   
    $status = '';

    if ($code === 0) {
        $status = 'OK';
    } elseif ($code === 1) {
        $status = 'WARNING';
    } else {
        $status = 'UNDEFINED';
    }

    return $status;
}

var_dump(getStatusByCode(null));
Enter fullscreen mode Exit fullscreen mode

So have you found it?

  • In the first case with the switch, the method returns OK.
  • In the second case, the method returns UNDEFINED.

But why this difference?

The first code with the switch comes from a legacy code base: no type hinting on the arguments, no return from the function. And this code was the cause of a small bug, because switch uses loose comparison: using == instead of === to compare values.

And in PHP with the loose comparison, null equals 0.

So be careful when you have a sequence of if / elseif / else, switching to switch can have an impact on the expected behavior.


So what to do?

If you follow me a little, I recommend that you use the strict comparison with === most often (if not all the time).

So if you want to keep this behavior, some ideas:

  • You leave your sequence of if / elseif / else
  • You reinforce your function parameters with types to ensure you never have an unwanted value (if that's the case)
function getStatusByCode(int $code)
{   
    $status = '';

    switch ($code) {
        case 0:
            $status = 'OK';
            break;

        case 1: 
            $status = 'WARNING';
            break;

        default:
            $status = 'UNDEFINED';
            break;
    }    

    return $status;
}

var_dump(getStatusByCode(null));

/* Result : Fatal error: Uncaught TypeError: 
 * Argument 1 passed to getStatusByCode() must be of the type int, null given
 */
Enter fullscreen mode Exit fullscreen mode
  • You are using match available since PHP 8 which uses strict comparison 👍
function getStatusByCode($code)
{
    return match($code) {
        0 => 'OK',
        1 => 'WARNING',
        default => 'UNDEFINED',
    };
}
Enter fullscreen mode Exit fullscreen mode

Thank you for reading, and let's stay in touch !

If you liked this article, please share. You can also find me on Twitter/X for more PHP tips.

Top comments (5)

Collapse
 
altesack profile image
Marat Latypov

Wow! This match is cool!

Collapse
 
bellinivitor profile image
Vitor Bellini Federle

Isn't it better to use an ENUM?

Collapse
 
klnjmm profile image
Jimmy Klein

The example is here to show the difference between loose comparaison (switch) and strict comparaison.

Enum or not, you will probably encountered a switch case in your code, and the goal here is to warn people of the loose comparaison.

Collapse
 
bellinivitor profile image
Vitor Bellini Federle

Hmmm, this part is well explained, great job!

Collapse
 
gemanzo profile image
Gennaro Manzo

Didn't know switch uses loose comparison, thank you for the advice!