Odd behaviour in a switch statement

前端 未结 2 1114
渐次进展
渐次进展 2020-12-07 01:43

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 the

相关标签:
2条回答
  • 2020-12-07 02:20

    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
    

    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 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] : '';
    }
    

    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.

    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.

    0 讨论(0)
  • 2020-12-07 02:21

    The key point is that a switch() statement performs comparisons between the parameter and the labels. That means that you have to deal with PHP comparison and type casting rules. Just see some examples:

    <?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)
    

    The reference can be found at:

    • http://es.php.net/manual/en/language.operators.comparison.php
    • http://es.php.net/manual/en/types.comparisons.php#types.comparisions-loose
    • http://es.php.net/manual/en/control-structures.switch.php

    Initializing an unset GET parameter to 0 is a pretty strange design decision. You should deal with that particular case in a separate fashion to make it clear that it's a special situation:

    if( $name===0 ){
        return '';
    }
    switch($name){
        // ...
    }
    
    0 讨论(0)
提交回复
热议问题