PHP那些“坑”

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

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)

ps: php 7 优化和不兼容

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

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 引用

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 +

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
)

浮点数精度问题

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 switch

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)
 $name = 0;
 switch ($name) {
          case "a":
               //...
               break;
          case "b":
               //...
               break;
     }
    switch (strval($name)) {
          case "a":
               //...
               break;
          case "b":
               //...
               break;
     }

strpos

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 文件上传

http://php.net/manual/zh/curlfile.construct.php

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

foreach 顺序

$arr=[];
$arr[2] = 2;
$arr[1]  = 1;
$arr[0]  = 0;
foreach ($arr as $key => $val) {
echo $val;// 2 1 0 
}
while (list($key, $v) = each($arr)) {
   //获取不到  foreach会自动reset,each之前, 先reset数组的内部指针
}
for($i=0,$l=count($arr); $i<$l; $i++) {
    echo $arr[$i];// 0 1 2
}

json_decode

>>> json_decode('php')
=> null
>>> json_decode('0x123')
=> 291

strtotime('-x month')

date_default_timezone_set('Asia/Shanghai');
$t = strtotime('2017-08-31');
echo date('Ym',strtotime('- 1 month',$t));//201707
echo date('Ym',strtotime('- 2 month',$t));//201707
// 
$first_day_of_month = date('Y-m',strtotime('2017-08-31')) . '-01 00:00:01';
$t = strtotime($first_day_of_month);
echo date('Ym',strtotime('- 1 month',$t));//201707
echo date('Ym',strtotime('- 2 month',$t));//201706
echo date("Ym", strtotime("-2 month", strtotime("first day of 2017-08-31")));//201706

原文发布于微信公众号 - php(phpdaily)

原文发表时间:2018-03-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Crossin的编程教室

【编程课堂】有序字典 OrderedDict

编程课堂将和每周一坑一样,成为本教室公众号的一个长期固定栏目。每期讲解一个编程知识点,包括但不限于 Python 语法、模块介绍、编程小技巧等。用简短的篇幅,让...

3728
来自专栏Java爬坑系列

【JAVA零基础入门系列】Day5 Java中的运算符

  运算符,顾名思义就是用于运算的符号,比如最简单的+-*/,这些运算符可以用来进行数学运算,举个最简单的栗子:   已知长方形的长为3cm,高为4cm,求长方...

2097
来自专栏jouypub

MySQL中utf8和utf8mb4的区别

MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。好在utf8mb4是ut...

1668
来自专栏Java Web

Java 面试知识点解析(四)——版本特性篇

1465
来自专栏iOS 开发杂谈

iOS RunTime之五:Category 面试题

很多人在面试的时候都会被问到 Category,既然允许用 Category 给类增加方法和属性,那为什么不允许增加成员变量?

3984
来自专栏铭毅天下

干货 | Elasticsearch5.X Mapping万能模板

0、引言 在关系型数据库如Mysql中,设计库表需要注意的是: 1)需要几个表; 2)每个表有哪些字段; 3)表的主键及外键的设定——便于有效关联。 表的设计遵...

48613
来自专栏Java学习网

Java面试题系列之基础部分(六)——每天学5个问题

Java基础部分学习的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io的语法,虚拟机方面的语法,这些都是最基...

2665
来自专栏项勇

笔记45 | 代码性能优化建议[转]

1396
来自专栏余林丰

Effective Java通俗理解(下)

第31条:用实例域代替序数   枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用...

2689
来自专栏JavaEdge

Netty 源码深度解析(九) - 编码概述1 抽象类 MessageToByteEncoder2 抽象类 MessageToMessageEncoder一个java对象最后是如何转变成字节流,写到s

编码器实现了ChannelOutboundHandler,并将出站数据从 一种格式转换为另一种格式,和我们方才学习的解码器的功能正好相反。Netty 提供...

3091

扫码关注云+社区

领取腾讯云代金券