美文网首页
PHP开发中的坑

PHP开发中的坑

作者: 程序员有话说 | 来源:发表于2019-02-12 15:17 被阅读0次

    一、md5和sha1的0e...的问题

    $md5_1 = md5('240610708');
    $md5_2 = md5('QNKCDZO');
    
    var_dump($md5_1);
    var_dump($md5_2);
    
    var_dump($md5_1 == $md5_2);
    
    $sha_1 = sha1('aaO8zKZF');
    $sha_2 = sha1('aa3OFF9m');
    
     var_dump($sha_1);
     var_dump($sha_2);
    
    var_dump($sha_1 == $sha_2);
    
    var_dump('0x1234Ab' == '1193131');
    
    var_dump( 0 == "a" ); //true
    var_dump( "0" == "a" ); //false
    
    
    解释

    由于 PHP 是弱类型语言,在使用 == 号时,如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行;两个字符串恰好以 0e 的科学记数法开头,字符串被隐式转换为浮点数,实际上也就等效于 0×10^0 ,因此比较起来是相等的

    解决方案

    PHP中的Hash校验,应该使用===,而不应该使用==。另外如果生产环境版本足够高的话(PHP >= 5.6.0),最好使用 hash_equals() 函数。

    二、数组返回null的函数

    error_reporting(0);
    
    error_reporting(0);
    
    $arr = [];
    
    var_dump(trim($arr) === null); //true
    
    var_dump(md5($arr) === null); //true
    
    var_dump(explode(',', $arr) === null); //true
    
    var_dump(strpos($arr, 'a')); //NULL  查找字符串首次出现的位置
    
    var_dump(strcmp($arr, 'a')); //NULL  二进制安全字符串比较
    
    

    三、foreach的引用与赋值

    $test=array('a','b','c');
    foreach($test as &$value){
        echo $value.'<br>';
    }
    echo $value.'<br>';
    
    foreach($test as $value){
        echo $value.'<br>';
    }
    echo $value;
    
    解释

    在第一个foreach中,我们使用了赋值引用符号,它的意思是每次遍历时,value指向的是test数组中的对应元素的地址,循环第一次时,value指向的是'a'的地址,第二次循环的时候,value指向的是第二个元素'b'的地址, 第三次循环时,value指向的就是'c'的地址。当我们在做第二次遍历的时候,其实value变量指向的还是test的第三个元素即'c'的地址。然后foreach本身的操作是把数组中对应的元素赋值给as后面的变量,所以在第二个foreach中, 遍历第一次的时候,把'a'赋值给value指向的地址(&test[2]),原有'c'所占的地址空间的值变为了'a',即['a','b','a'], 第二次遍历的时候,把'b'赋值给value指向的地址即['a','b','b'], 第三次遍历的时候,就把'b'赋值给$value指向的地址,最终结果['a','b','b']的原因。

    解决方案

    在使用完赋值引用操作符之后,把变量unset掉,上例中加上unset(value)语句,相当于取消value对该地址的引用,这样第二次foreach的时候,$value相当于新的变量,不会导致上述问题。这也是一个很好的编程习惯。

    四、精度问题

    var_dump((0.1 + 0.7) === 0.8);//boolean false
    var_dump((0.1 + 0.7) * 10 === 0.8 * 10);//boolean false
    var_dump((0.1 + 0.7) * 100 === 0.8 * 100);//boolean true
    echo intval(0.58 * 100);//57
    echo intval(0.58 * 1000);//580
    
    
    

    PHP浮点数的一个常见问题的解答

    解释

    不要用浮点数进行比较和数学运算转化为整型运算

    解决方案

    试用bcmath库(php自带)

    四、整型溢出

    $a = intval(21474836478);
    var_dump($a);
    $b = intval(2570);
    $c = intval(21474839050);
    var_dump($b === $c);
    
    
    解释

    PHP的整型数的字长和平台有关,对于32位的操作系统,最大的整型是2147483647(2^31),最小为 -2^31。可以表示4294967296个数字,有符号的话就是-2147483647到2147483648

    解决方案

    php里的办法就是:不能使用intval,用floatval取代之。
    a = 21474836470; 看上去是整数,实际是浮点数;a = floatval(21474836470 ) 确保是一个数字

    五、优先级

    echo -10%3; // -1
    
    

    因为-的优先级比%求余的优先级低,也就是-(10%3)。

    ini_set('display_errors',0);
    $arr = array(1=>1,3=>3);
    $i = 2;
    $a = 'test' . isset($arr[$i]) ? $arr[$i] : $i; //null
    
    

    因"."的优先级高于三元运算符"?:"。所以程序其实报错了。会说$arr的索引2不存在。

    $a = 3;
    $b = 5;
    if($a = 5 || $b = 7) {
        $a++;
        $b++;
    }
    echo $a . " " . $b;  // 1 6
    

    因"="的优先级低于"||",所以先逻辑判断再赋值。也就是(a = (5 ||b = 7))。所以,最后其实给a赋值true了,$a等于1.

    $x = 2;
    echo $x == 2 ? '我' : $x == 1 ? '你' : '它'; //你
    
    因为 == 的优先级比三元运算符高
    
    $x = 2;//将2赋值给变量x 
    echo true ? '我' : false ? '你' : '它';
    //由于三元运算符左结合的特性 所以如上代码等效于
    echo (true ? '我' : false) ? '你' : '它';
    //先计算左边括号里的
    echo '我' ? '你' : '它';
    

    因"=="的优先级高于"?:"

    六、include

    //file1.php
    <?php
    $a = '123';
    ?>
    //file2.php
    <?php
    echo include('file1.php'); //1
    ?>
    

    因include()也是一个函数,有返回值。在成功时返回1,失败时返回错误信息。如果被包含的文件有return,则inculde()成功时返回该文件的返回值。

    七、static和++

    <?php
    $count = 5;
    function get_count() {
        static $count = 0;
        return $count++;
    }
    ++$count;
    echo $count; //6
    echo get_count(); //0
    echo get_count(); //1
    ?>
    

    因static count,所以只在第一次调用get_count的时候对count赋值为0,第二次再进来这个函数,则不会第二次赋值。其次就是return count++和return ++count了,前者先返回,后者先++再返回。

    八、类型转换

    <?php
    $arr = array(0 =>1,'aa' => 2,3,4);
    foreach($arr as $key => $val){
        print($key == 'aa' ? 5 : $val);
    }
    //5534
    ?>
    

    因遍历数组第一次的时候,$key和aa的比较实际就是0和aa的比较,一个是int一个是string,这个时候会转换类型,将字符串转换为数字再与数字比较。所以0=='aa'就是0==0,所以为true,也就是输出5。

    九、count的用法

    echo count (false); //1
    $a = count ("567")  + count(null) + count(false);
    echo $a;//2
    

    如果不是数组或者对象的其他类型,返回1.那么这个值应该就是1+0+1了

    十、++和&

    <?php
    
    $arr = array(1,2,3);
    foreach($arr as &$val) {
        echo $val % 2; //1,0,1
        $val += $val % 2 ? $val++ : $val--;
    }
    print_r($arr);
    $val = 0;
    print(join('',$arr));
    
    //101Array ( [0] => 3 [1] => 3 [2] => 7 ) 330
    ?>
    

    因foreach结束后的数组应该是array(3,3,7);最后给第三个元素赋值为0,所以就是330了。其中注意的是&,如果有&则是对原变量操作,如果没有,则是先生成一个新变量,然后给这个变量复制,最后操作的是这个新变量。

    相关文章

      网友评论

          本文标题:PHP开发中的坑

          本文链接:https://www.haomeiwen.com/subject/mlgrrqtx.html