lang2
lang2

Reputation: 11966

php null value confusion in switch statement

I have the following php code that gives me an unexpected result:

$foo = NULL;

switch($foo)
{
    case 0:
        print "What?!";
}

I'd expect the result to be nothing, but it matches case 0. The php manual says that NULL is a non-value, so how can it equal 0?

Upvotes: 32

Views: 26361

Answers (8)

Script47
Script47

Reputation: 14540

As of PHP 8, you can use the match expression:

The match expression branches evaluation based on an identity check of a value.

Similarly to a switch statement, a match expression has a subject expression that is compared against multiple alternatives.

Unlike switch, it will evaluate to a value much like ternary expressions. Unlike switch, the comparison is an identity check (===) rather than a weak equality check (==).

Match expressions are available as of PHP 8.0.0.

Per your example:

$foo = null;

$value = match($foo) {
    0 => print('What?')
};

Will output:

Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type null

So you can add a try/catch and handle it accordingly or add a default "catch-all":

$compare = null;

$value = match($compare) {
    0 => print('What?'),
    default => print('Default!')
};

Upvotes: 1

Chloe Fletcher
Chloe Fletcher

Reputation: 11

You can do what I did - it's lazy but it works. Before running the switch, I checked if the value is null and, if so, changed it to something known:

IF ($foo==null) {
     $foo == 99;
}
switch($foo)
{
    case 99:
        print "This is NULL"; break;
    case 0:
        print "What?!";
}

Upvotes: 1

tola
tola

Reputation: 152

EDIT: The inaccuracy is with my testing, and it was pointed out to me. Check the comments, if you are interested.

From what I've tested, the top answer is inaccurate. It seems as though a PHP switch statement sees NULL as a "joker", and applies any case to it. I tried with different numbers and with a string, and they all fired. Nothing there suggests it should be NULL, not even on PHP loose comparison. So my suggestion is adding a case NULL: at the start, just as you add default at the end.

    $foo = NULL;

    switch($foo)
    {
        case NULL:
            print "This is NULL"; break;
        case 0:
            print "What?!";
    }

Upvotes: 0

RajeshK
RajeshK

Reputation: 461

This can be also written like

$foo = NULL;

switch( true )
{
    case ( 0 === $foo ):
        print "What?!";
    default:
        print "Default?!";
}

Upvotes: 5

SergeS
SergeS

Reputation: 11779

beacuse php is not type strict language

$foo = NULL;

if( isset( $foo ) ) {
    switch( $foo ) {
        case 0:
            print "WTF!!!";
    }
}

Upvotes: 7

borrible
borrible

Reputation: 17366

The switch statement applies loose comparison which means that the following things are treated as equivalent to 0:

false
0
"0"
NULL
"any string"
""

Upvotes: 40

Daren Thomas
Daren Thomas

Reputation: 70324

I'm assuming here, but it could be that the switch statement coerces the value of $foo when comparing to 0. To test this hypothesis, why don't you try adding this above the switch statement:

echo $foo == NULL;

This should echo 1 before the curse, if I'm correct...

Upvotes: 0

Delan Azabani
Delan Azabani

Reputation: 81404

PHP is doing a type-coerced, weak comparison. You will need to do this instead:

$foo = NULL;
if ($foo === 0)
    print "WTF!!!";

Upvotes: 1

Related Questions