switch 语句中的奇怪行为 [英] Odd behaviour in a switch statement

查看:24
本文介绍了switch 语句中的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing code for a sortable table, where clicking the links in the header change the ORDER BY executed when generating a set of search results (the case where there there is no valid order by causes the query to not be run with order by and just return the results in the order the database returns. this is as designed). The code is being written within a framework provided by my employer.

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

To validate the ORDER BY part of the query I run the input through the following validation function.

<?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 整数作为其输入,它将始终遵循第一个可用的执行路径.

Under testing I discovered that if no parameter was provided then the sort order would be resnum. After some experimentation, I discovered that the filtering built into the framework would cause a request for an uninitialized variable such as an unset GET parameter to return integer 0. If the above code got fed a 0 integer as its input it would always follow the first path of execution available to it.

作为一个实验,我尝试在 switch 语句中重新排列 case 的顺序,发现如果这个函数被传递一个 0,那么顶部的内容就是执行的内容.

As an experiment I tried rearranging the order of the cases in the switch statement, and found whatever was at the top would be what was executed if this function was passed a 0.

问题的解决方案是使用 switch (strval($name)) 来解决特定问题,但现在我很好奇 PHP switch 语句的一般行为.我目睹的行为是 PHP 的正确行为吗?PHP 中是否存在导致此问题的错误,或者我在代码中犯了一个我不知道的错误?

The solution to the problem was using switch (strval($name)) so the particular problem is solved, but now I'm curious as to the general behaviour of PHP switch statements. Is the behaviour I witnessed the correct behaviour for PHP? Is there some fault in PHP that's causing this, or have I made an error in my code of which I'm not aware?

推荐答案

这是因为 php 将字符串转换为整数的方式.当你传入一个 0 时,你要求它进行整数比较,所以它会将你所有的 case 键转换为整数.当 php 将 string 转换为 int 时,它会在字符串的开头查找一个实际的数字,然后将这个数字吞噬到一个非数字为止.由于字符串resnum"没有数字,所以它返回 0.见这里:

It's because of the way php casts strings to ints. When you pass in a 0, you are asking it to do an integer comparison, so it will convert all of your case keys to integers. When php casts a string to an int, it looks for an actual number at the beginning of the string, and gobbles the number up until it hits a non-number. Since the string "resnum" has no numbers, it returns 0. See here:

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.

Since all of those strings cast to 0, the first case would evaluate to true since 0 == 0.

资源:
字符串转换为数字
类型比较表

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

Nitpick time. When you're doing simple case statements that map a string to a string, use an array. It's much clearer and actually faster:

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 的情况.

If the $name is set in the map, we return the value that key is mapped to. Otherwise, we return an empty string, which takes the place of the default case.

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

As a bonus, you would have noticed the bug earlier if you did the above method, because it would be trying to access $modeMap[0] and would have returned your default case instead.

这篇关于switch 语句中的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆