make switch use === comparison not == comparison In PHP

Viewed 19797

Is there anyway to make it so that the following code still uses a switch and returns b not a? Thanks!

$var = 0;
switch($var) {
    case NULL : return 'a'; break;
    default : return 'b'; break;
}

Using if statements, of course, you'd do it like this:

$var = 0;
if($var === NULL) return 'a';
else return 'b';

But for more complex examples, this becomes verbose.

16 Answers

Here is your original code in a "strict" switch statement:

switch(true) {
    case $var === null:
        return 'a';
    default:
        return 'b';
}

This can also handle more complex switch statement like this:

switch(true) {
    case $var === null:
        return 'a';
    case $var === 4:
    case $var === 'foobar':
        return 'b';
    default:
        return 'c';
}

Yes. On PHP 8 you can do it with match statement.

Unlike switch, the comparison is an identity check (===) rather than a weak equality check (==). Match expressions are available as of PHP 8.0.0.

See here: https://www.php.net/manual/en/control-structures.match.php

$var=0;
echo match ($var) {
    NULL=> 'a',
    default => 'b'
};

Create an assertion-like class and put whatever logic you want in it; so long as "true" methods return $this (and nothing else to avoid false-positives.)

class Haystack
{
    public $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function isExactly($n)
    {
        if ($n === $this->value)
            return $this;
    }
}

$var = new Haystack(null);

switch ($var) {
    case $var->isExactly(''):
        echo "the value is an empty string";
        break;

    case $var->isExactly(null):
        echo "the value is null";
        break;
}

Or you can put your switch inside the actual class:

class Checker
{
    public $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function isExactly($n)
    {
        if ($n === $this->value)
            return $this;
    }

    public function contains($n)
    {
        if (strpos($this->value, $n) !== false)
            return $this;
    }

    public static function check($str)
    {
        $var = new self($str);

        switch ($var) {
            case $var->isExactly(''):
                return "'$str' is an empty string";
            case $var->isExactly(null):
                return "the value is null";
            case $var->contains('hello'):
                return "'$str' contains hello";
            default:
                return "'$str' did not meet any of your requirements.";
        }
    }
}

var_dump(Checker::check('hello world'));   # string(28) "'hello world' contains hello"

Of course that that point you might want to re-evaluate what you want to do with what you're checking and use a real validation library instead.

If you want to test both value and type of your variable, then build a new string variable containing both informations and compare it with your different scenarios (by concatenation) it should work for your case if you implement all possible types (according to gettype() documentation), example :

<?php
    $var= 9999;
    $valueAndTypeOfVar = (string)$var.' '.gettype($var);
    switch($valueAndTypeOfVar) {
        case "$var boolean" : echo 'a'; break;
        case "$var integer" : echo 'b'; break; 
        case "$var double" : echo 'c'; break;
        case "$var string" : echo 'd'; break; 
        case "$var array" : echo 'e'; break;
        case "$var object" : echo 'f'; break; 
        case "$var resource" : echo 'g'; break;
        case "$var NULL" : echo 'h'; break; 
        case "$var unknown type" : echo 'i'; break; 
        default: echo 'j'; break;
    }

   // Outputs: 'b'
?>
Related