php - switch 语句中的奇怪行为

标签 php switch-statement

我正在为可排序表编写代码,单击标题中的链接会更改生成一组搜索结果时执行的 ORDER BY(没有有效排序的情况会导致查询无法运行使用 order by 并按照数据库返回的顺序返回结果。这是设计的)。代码是在我的雇主提供的框架内编写的。

为了验证查询的 ORDER BY 部分,我通过以下验证函数运行输入。

<?php
function sortMode ($name)
{
    $mode   = '';
    switch ($name)
    {
        case 'resnum'   : $mode = 'b_resnum';            break;
        case 'state'    : $mode = 'st_id';               break;
        case 'name'     : $mode = 'lastname, firstname'; break;
        case 'phone'    : $mode = 'phone';               break;
        case 'email'    : $mode = 'email';               break;
        case 'opened'   : $mode = 'cs_created';          break;
        default         : $mode = '';                    break;
    }
    return ($mode);
}
?>

在测试中,我发现如果没有提供任何参数,那么排序顺序将是 resnum。经过一些实验,我发现框架内置的过滤会导致对未初始化变量(例如未设置的 GET 参数)的请求返回整数 0。如果上面的代码得到一个 0 整数作为其输入,它将始终遵循第一个它可用的执行路径。

作为实验,我尝试重新排列 switch 语句中 case 的顺序,发现如果此函数传递 0,则顶部的内容将被执行。

问题的解决方案是使用 switch (strval($name)) 因此特定问题已解决,但现在我对 PHP switch 语句的一般行为感到好奇。我目睹的行为是 PHP 的正确行为吗?是 PHP 中的某些错误导致了这种情况,还是我在我的代码中犯了一个我不知道的错误?

最佳答案

这是因为 php 将字符串转换为整数的方式。当您传入 0 时,您要求它进行整数比较,因此它会将您的所有 case 键转换为整数。当 php 将 string 转换为 int 时,它会在字符串的开头查找实际数字,并吞噬该数字,直到遇到非数字。由于字符串“resnum”没有数字,因此它返回 0。请参见此处:

php > echo (int)"100";
100
php > echo (int)"300 dogs";
300
php > echo (int)"resnum";
0
php > echo (int)"resnum 100";
0

由于所有这些字符串都转换为 0,因此第一种情况的计算结果为 true,因为 0 == 0

资源:
String conversion to numbers
Type comparison tables


吹毛求疵的时间。当您执行将字符串映射到字符串的简单 case 语句时,请使用数组。它更清晰,实际上更快:

function sortMode ($name)
{
    $modeMap = array(
        'resnum'   => 'b_resnum',
        'state'    => 'st_id',
        'name'     => 'lastname, firstname',
        'phone'    => 'phone',
        'email'    => 'email',
        'opened'   => 'cs_created'
    );

    return isset($modeMap[$name]) ? $modeMap[$name] : '';
}

如果在映射中设置了 $name,我们将返回键映射到的值。否则,我们返回一个空字符串,它取代了 default 的情况。

作为奖励,如果您执行上述方法,您会更早地注意到该错误,因为它会尝试访问 $modeMap[0] 并且会返回您的默认情况。

关于php - switch 语句中的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4098104/

相关文章:

javascript - 使用 google API 和 javascript 的 PHP 项目 : Inherited Mess

c# - RadioButton 和开关

JavaScript Switch 语句 - 以防万一的条件

c++ - Switch 语句 C++ 的问题

java - Java 1.8 中的 switch-case 与 Eclipse 不可能吗?

php - 在 foreach 循环中返回数组

php - Docker php : What are the :zts php images on Docker Hub

php - 使用 API 将模块的数据暴露给 Views2

php - 客户姓名、手机号码和描述 获取但不获取地址 为什么?

java - 用映射替换 switch 语句(针对不同的数据类型)