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

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

问题描述

我正在为可排序表编写代码,其中单击标题中的链接会更改在生成一组搜索结果时执行的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语句中重新排列大小写的顺序,发现最上面的内容将是如果将此函数传递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时,您要求它进行整数比较,因此它将所有大小写键都转换为整数.当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,因此从0 == 0开始,第一种情况的计算结果为true.

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

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

Resources:
String conversion to numbers
Type comparison tables

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

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天全站免登陆