字符串 == 比较类型强转隐患

  1.  
  2. //http://php.net/manual/zh/language.operators.comparison.php  php 5
    
    var_dump(md5('240610708') == md5('QNKCDZO'));//bool(true)
    
    var_dump(md5('aabg7XSs') == md5('aabC9RqS'));//bool(true)
    
    var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));//bool(true)
    
    var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m'));//bool(true)
    
    var_dump('0010e2' == '1e3');//10×10^2 = 1×10^3  bool(true)
    
    var_dump('0x1234Ab' == '1193131');//bool(true)
    
    var_dump('0xABCdef' == ' 0xABCdef');//bool(true)
    
    var_dump('0e1' == '0e2'); //bool(true)
    
    // php 7 含十六进制字符串不再被认为是数字 http://php.net/manual/zh/migration70.incompatible.php
    
    var_dump('0x1234Ab' == '1193131');//bool(false)
    
    var_dump('0xABCdef' == ' 0xABCdef');//bool(false)
    
    var_dump("0x123" == "291");//bool(false)
    
    var_dump(is_numeric("0x123"));//bool(false)
    
    >>> md5('240610708')
    
    => "0e462097431906509019562988736854"
    
    >>> md5('QNKCDZO')
    
    => "0e830400451993494058024219903391"
    
    // php 是弱语言,会自动判断数据类型,0eXXXXXXXXXX 转成 0 了
    
    //来自文档:如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行。此规则也适用于 switch 语句。当用 === 或 !== 进行比较时则不进行类型转换,因为此时类型和数值都要比对。
    
    >>> md5('QNKCDZO')==0
    
    => true
    
    >>> md5('240610708')==0
    
    => true
    
    // 使用 === 判断 官方都建议直接用password_hash加密
    
    var_dump(md5('240610708') === md5('QNKCDZO'));//bool(false)
    
    
    //把你的密码设成 0x1234Ab,然后退出登录再登录,换密码 1193131 登录,如果登录成功,那么密码绝对是明文保存的。 
    
    //同理,密码设置为 240610708,换密码 QNKCDZO 登录能成功,那么密码没加盐直接md5保存的。

ps: php 7 优化和不兼容

PHP 那些“坑”_浮点数

PDO bindParam 要求第二个参数是一个引用变量

  1. //http://www.laruence.com/2012/10/16/2831.html
    
    $dbh = new PDO('mysql:host=localhost;dbname=test', "test");
    
    $query = <<<QUERY
    
     INSERT INTO `user` (`username`, `password`) VALUES (:username, :password);
    
    QUERY;
    
    $statement = $dbh->prepare($query);
    
    $bind_params = array(':username' => "laruence", ':password' => "weibo");
    
    foreach( $bind_params as $key => $value ){
    
       $statement->bindParam($key, $value);
    
    }
    
    $statement->execute();
    
    //期望执行 sql
    
    INSERT INTO `user` (`username`, `password`) VALUES ("laruence", "weibo");
    
    // 实际执行 sql
    
    INSERT INTO `user` (`username`, `password`) VALUES ("weibo", "weibo");
    
    //第一次循环
    
    $value = $bind_params[":username"];
    
    $statement->bindParam(":username", &$value); //此时, :username是对$value变量的引用
    
    //第二次循环
    
    $value = $bind_params[":password"]; //oops! $value被覆盖成了:password的值
    
    $statement->bindParam(":password", &$value);
    
    // 解决
    
    foreach( $bind_params as $key => &$value ) { //注意这里
    
       $statement->bindParam($key, $value);
    
    }
    
    return $statement->execute($params);


PHP 引用

  1. //https://glot.io/snippets/estgofa359
    
       $arr = range(1,3);
    
       foreach($arr as &$v){
    
       }
    
       foreach($arr as $v){
    
       }
    
       print_r($arr);//[1,2,2]
    
    // 解决一
    
      $arr = range(1,3);
    
       foreach($arr as &$v){
    
       }
    
       unset($v);
    
       foreach($arr as $v){
    
       }
    
       print_r($arr);//[1,2,3]
    
    // 解决二
    
       $arr = range(1,3);
    
       foreach($arr as &$v){
    
       }
    
       foreach($arr as $v2){
    
       }
    
       print_r($arr);//[1,2,3]
    
    // 解决三
    
       $arr = range(1,3);
    
       foreach($arr as &$v){
    
       }
    
       foreach($arr as &$v){
    
       }
    
       print_r($arr);//[1,2,3]


    array_merge vs +

  1. //https://glot.io/snippets/estgpi43bc
    
    $arr1 = array(1 => "one", "2" => "two", 3 => "three");
    
    $arr2 = array(2 => "new two", 3 => "new three");
    
    print_r($arr1 + $arr2);
    
    Array
    
    (
    
       [1] => one
    
       [2] => two
    
       [3] => three
    
    )
    
    print_r(array_merge($arr1, $arr2));
    
    Array
    
    (
    
       [0] => one
    
       [1] => two
    
       [2] => three
    
       [3] => new two
    
       [4] => new three
    
    )


    浮点数精度问题

PHP 那些“坑”_浮点数_02

  1. http://php.net/manual/zh/language.types.float.php
    
    var_dump(15702>=(157.02*100));//bool(false)
    
    var_dump(11111>=(111.11*100));//bool(true)
    
    var_dump(bcsub(15702,(157.02*100)) >= 0);//bool(true)
    
    if(abs(15702-(157.02*100)) < 0.001) {
    
       echo "相等";
    
    } else {
    
       echo "不相等";
    
    }
    
    $f = 0.58;
    
    var_dump(intval($f * 100)); //57 0.58 * 100 = 57.999999999...


in_array

  1. //https://glot.io/snippets/esth249n0y
    
    $arr = ['a', 'pro' => 'php', 8, true];
    
    var_dump(in_array(2, $arr)); // bool(true)
    
    var_dump(in_array('b', $arr)); // bool(true)
    
    var_dump(in_array(0, $arr)); // tbool(true)
    
    var_dump(in_array(null, $arr)); // bool(false)
    
    var_dump(in_array(2, $arr, true)); // bool(false)
    
    var_dump(in_array(0, $arr, true)); // bool(false)


strpos

  1. //https://glot.io/snippets/esthlvjtki
    
    function getReferer($link)
    
    {
    
       $refMap = [
    
           'baidu' => '百度',
    
           'sougou' => '搜狗',
    
           '360' => '360',
    
           'google' => '谷歌'
    
       ];
    
       foreach ($refMap as $key => $value) {
    
           if (strpos($link, $key) !== false) {
    
               return $value;
    
           }
    
       }
    
       return '其他';
    
    }
    
    // https://secure.php.net/manual/zh/function.strpos.php 如果 needle 不是一个字符串,那么它将被转换为整型并被视为字符的顺序值。
    
    echo getReferer('https://www.google.com/search?workd=google');//360
    
    // 解决
    
    function getReferer($link)
    
    {
    
       $refMap = [
    
           'baidu' => '百度',
    
           'sougou' => '搜狗',
    
           '360' => '360',
    
           'google' => '谷歌'
    
       ];
    
       foreach ($refMap as $key => $value) {
    
           if (mb_strpos($link, $key) !== false) {
    
           //if (strpos($link, strval($key)) !== false) {
    
               return $value;
    
           }
    
       }
    
       return '其他';
    
    }


cURL 文件上传

  1. /

    /PHP的cURL支持通过给CURL_POSTFIELDS传递关联数组(而不是字符串)来生成multipart/form-data的POST请求 http://php.net/manual/zh/curlfile.construct.php
    
    if (class_exists('\CURLFile')) {
    
       $field = array('fieldname' => new \CURLFile(realpath($filepath)));
    
    } else {
    
       $field = array('fieldname' => '@' . realpath($filepath));
    
    }