代码之家  ›  专栏  ›  技术社区  ›  GordonM

switch语句中的奇怪行为

  •  7
  • GordonM  · 技术社区  · 15 年前

    为了通过查询的一部分验证订单,我通过下面的验证函数运行输入。

    <?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。经过一些实验,我发现框架中内置的过滤会导致对未初始化变量(如unset GET参数)的请求返回整数0。如果上面的代码输入了一个0整数,那么它将始终遵循可用的第一个执行路径。

    解决这个问题的办法是 switch (strval($name)) 所以这个问题已经解决了,但是现在我想知道PHP switch语句的一般行为。我看到的行为是否适合PHP?是PHP中的某些错误导致了这种情况,还是我的代码中出现了一个我不知道的错误?

    2 回复  |  直到 9 年前
        1
  •  12
  •   ryeguy    15 年前

    这是因为php将字符串转换为int的方式。当你经过一个 0 ,您要求它进行整数比较,以便将所有大小写键转换为整数。当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
    

    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 案例。

    另外,如果您使用上述方法,您会更早地注意到这个bug,因为它将尝试访问 $modeMap[0]

        2
  •  0
  •   Álvaro González    15 年前

    关键是switch()语句执行参数和标签之间的比较。这意味着您必须处理PHP比较和类型转换规则。请看一些例子:

    <?php
    
    var_dump( ''==0 );    // bool(true)
    var_dump( 'foo'==0 ); // bool(true)
    var_dump( '0'==0 );   // bool(true)
    var_dump( '0m'==0 );  // bool(true)
    var_dump( '01'==0 );  // bool(false)
    

    可在以下位置找到参考:

    if( $name===0 ){
        return '';
    }
    switch($name){
        // ...
    }