使用 strstr 的 Switch 语句总是验证为真?

Switch statement using strstr always validates as true?

我有以下 switch 语句。

URL 包含推介 ID,例如 twitter、facebook 或电子邮件,例如 mail@mail.com。这存储为 $ref

我有以下 switch 语句:

switch ($ref) {
    case "twitter":
        echo "twitter";
        break;
    case "facebook":
        echo "facbeook";
        break;
    case "blog":
        echo "blog";
        break;
    case strstr($ref,'@'):
        echo "email = ".$ref;
    default:
        echo "no referral found";
        break;
}

然而,如果 URL 没有传递任何内容(例如 www.mything.co.uk),那么我希望转到 default 案例。

相反,我得到以下输出:

email = no referral found

为什么默认还包括我为 case strstr($ref,'@') 设置的文本?

那是因为您的测试执行方式类似于 if ($ref == strstr($ref, '@')),其中 strstr returns false 等于空字符串。您不能真正在 switch 语句中使用动态比较。如果需要,请使用 if..else。或者,滥用 switch 一点:

switch (true) {
    case $ref == 'twitter':
       ..
    case strstr($ref, '@'):
       ..
}

这会起作用:

case (strstr($ref, '@') ? true : false):

但这并不是很好的练习。

$ref为空字符串时,strstr($ref,'@');return也是空字符串,这就是为什么case strstr($ref,'@'):匹配开关输入$ref. 问题是,您甚至不能使用

这样的电子邮件验证功能
 filter_var($ref, FILTER_VALIDATE_EMAIL)

在空输入而不是空字符串的情况下 return false,但是 switch 进行松散比较,这意味着 "" == false 会 return true:

http://php.net/manual/en/types.comparisons.php#types.comparisions-loose

因此,我看到的唯一解决方案是使用 === 运算符的 if 语句:

if($ref == 'twitter') {
        echo "twitter";
} else if($ref == 'facebook') {
        echo "facbeook";
} else if($ref == 'blog') {
        echo "blog";
} else if($ref === filter_var($ref, FILTER_VALIDATE_EMAIL)) {
        echo "email = ".$ref;
} else {
        echo "no referral found";
}

OP 问题:“为什么默认值还包括我为 case strstr($ref,'@') 设置的文本?

答案:输出后没有break;,因此通过进入默认情况。

更新: 解决在 case 中放置语句的问题,我还提供了一个简单的解决方法:

switch ($ref) {
    case "twitter":
        echo "twitter";
        break;
    case "facebook":
        echo "facbeook";
        break;
    case "blog":
        echo "blog";
        break;
    default:
        if (strstr($ref,'@')) {
          echo "email = ".$ref;
        } else {
          echo "no referral found";
        }
        break;
}