Be careful about the switch statement in PHP
Jimmy Klein

Jimmy Klein @klnjmm

About: Hi, it's Jimmy 👋, PHP 🐘 developper, guitarist 🤘 and minimalist apprentice. I help developers progress in PHP.

Location:
Macon, France
Joined:
Jan 19, 2018

Be careful about the switch statement in PHP

Publish Date: Feb 22 '24
4 5

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.

Comments 5 total

  • Vitor Bellini Federle
    Vitor Bellini FederleFeb 23, 2024

    Isn't it better to use an ENUM?

    • Jimmy Klein
      Jimmy KleinFeb 23, 2024

      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.

  • Marat Latypov
    Marat LatypovFeb 27, 2024

    Wow! This match is cool!

  • Gennaro Manzo
    Gennaro ManzoFeb 27, 2024

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

Add comment