使开关使用===比较而不==比较在PHP中


78

无论如何,要使下面的代码仍然使用一个开关,b而不返回它,是a吗?谢谢!

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

当然,如果使用if语句,您将像这样:

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

但是对于更复杂的示例,这变得很冗长。

Answers:


55

抱歉,您不能===在switch语句中使用比较,因为根据switch()文档

请注意,开关/外壳确实比较宽松。

这意味着您必须提出解决方法。从松散的比较表,你可以利用的事实NULL == "0"是类型转换错误:

<?php
$var = 0;
switch((string)$var) 
{
    case "" : echo 'a'; break; // This tests for NULL or empty string   
    default : echo 'b'; break; // Everything else, including zero
}
// Output: 'b'
?>

现场演示


1
好吧,还有其他一些我想使用的环境(不仅仅是NULL)。
亚伦·尤代肯

18

这是“严格”开关语句中的原始代码:

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

这也可以处理更复杂的switch语句,如下所示:

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

8

不使用switch-仅进行所谓的“松散”比较。您始终可以使用将其替换为一个if/else if===


您是指您的经验还是文档?如果是后者,请张贴链接
TMS

1
实际上,您可以使用switch(请参见我的答案)执行此操作,尽管我确实认为这if-else对特定工作更好。
DaveRandom 2012年

很多好的答案,对不起,我只能选择1。我与if / elseif一起感谢大家。
yar matie 2012年

实际上不是“总是” :)如果不是所有case块都具有breakreturn呢?
风暴


3

在包含数字的字符串的交换机中,我遇到了同样的问题(在PHP的交换机中,“ 15.2”等于“ 15.20”)

我解决了在文本进行比较之前添加字母的问题

$var = '15.20';
switch ('#'.$var) {
    case '#15.2' :
      echo 'wrong';
    break;
    case '#15.20' :
      echo 'right';
    break;
}

1

使开关使用===比较而不==比较在PHP中

不幸的是,switch使用了松散的比较,据我所知,没有办法对此进行更改。



1

我只是用

$var === null and $var = -1; // since switch is not type-safe
switch ( $var ) {
    case 0:
        # this tests for zero/empty string/false
        break;
    case -1:
        # this tests for null
        break;
}

我认为,如果//留下以开头的注释(并且#最好以开头删除的注释),它仍然看起来很可读。



1

从您的示例代码推断,我想您有很多常规情况和一个特殊情况(在此处null)。

我能想到的最简单的方法是在切换之前处理这种情况:

if ($value === null) {
    return 'null';
}

switch ($value) {
    case 0:
        return 'zero';
    case 1:
        return 'one';
    case 2:
        return 'two';
}

也许还要添加一条注释,以记住null会意外地匹配0大小写(相反,0也会匹配null大小写)。


0

这是不可能的。

你可以,但是,把if报表里面switch

switch($var) {
    // Loose cases here

    case 0:
        if($var === NULL) {
            return 'a';
        }

        // Fall through

    default:
        return 'b';
}

或者简单地:

switch($var) {
    // Loose cases here

    default:
        if($var === NULL) {
            return 'a';
        }

        return 'b';
}

7
那时候为什么还要打扰开关呢?您甚至可以执行`switch(true){case $ var === null:...}
ircmaxell,2010年

1
@ircmaxell,我以为OP希望使用直通逻辑,或者switch有时是使用超出严格检查范围的原因。
斯特拉格

0

您还可以打开变量的类型:

switch (gettype($var)) {
...
}

坏主意-来自文档:Never use gettype() to test for a certain type, since the returned string may be subject to change in a future version. In addition, it is slow too, as it involves string comparison. Instead, use the is_* functions.
Peter Ajtai

如果gettype()更改,将使函数无用且语言可靠性降低。使用is_ *不能回答有关开关的问题。对于其余的我,我同意:)
greg 2012年

0

最好的方法之一是通过使用来检查NULL值 is_null

<?php
echo getValue();
function getValue()
{
    $var = 0;   
    switch(true) {
        case is_null($var) : return 'a'; break;
        default : return 'b'; break;
    }
}
?>

1
但是最好的是,=== null因为它避免了不必要的函数调用开销。
Antti29年

0

创建一个类似断言的类,并将所需的任何逻辑放入其中;只要返回“ true”方法$this(就没有其他方法可以避免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;
}

或者,您可以将开关放入实际的类中:

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"

当然,到那时,您可能希望重新评估要检查的内容,并使用真实的验证库。


0

如果要测试变量的类型,然后构建一个包含这两种信息的新字符串变量,并将其与不同的方案(通过串联)进行比较,则在实现所有可能的类型(根据gettype( )文档),例如:

<?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'
?>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.