zoukankan      html  css  js  c++  java
  • php新手常见问题

    10、filesize缓存的问题

    php的filesize居然会缓存(当然还有不少,这里仅用filesize举例,其它会缓存的函数,以官方文档为准)
    线上代码经常随机出各种问题,排查了1个月,线上加各种日志,最终发现是filesize缓存的问题,如下代码:

    [php] view plain copy

    echo filesize("a.txt");
    exec("rm a.txt"); // 删除文件
    echo filesize("a.txt"); // 这里会输出大小,而不是报错说文件不存在

    echo filesize("b.txt");
    echo filesize("a.txt"); // 这里会报错文件不存在,因为只缓存最后一个文件,缓存里只有b,没有a的缓存了
    看到了吧,filesize不仅有缓存,而且还只缓存最后一个文件,所以说PHP的开发人员也不知道怎么考虑的,就不会加个filesize_withcache方法?
    知道了原因,解决也就简单了,在filesize调用前清除缓存,加代码: clearstatcache()
    参考官方文档:http://php.net/manual/zh/function.filesize.php

    9、保存源码文件时,注意要使用utf-8无bom签名

    之前用Windows的记事本编辑文件,发布到Linux上线后,一直报错:Cannot modify header information - headers already sent by (output started at xxx.php:1)
    用Winmerge或BeyondCompare对比代码也无法发现问题,后来用Netbeans才发现文件最前面多了一个不可见字符,研究后才知道是Windows的Bom签名
    也就是说,在Windows上开发,在Linux上发布,注意要使用不支持Bom的编辑器,如果用VisualStudio要选择高级保存选项里的不带签名

    1、null和空、0、false等四个值的比较

    在PHP中,== 会先进行类型转换,再进行对比,而===会先比较类型,如果类型不同直接返回不相等,参考如下示例

    [php] view plain copy

    $a = null; $b = ''; $c = 0; $d = false;
    echo ($a == $b)?1:0; // 输出1
    echo ($a === $b)?1:0; // 输出0
    echo ($a == $c)?1:0; // 输出1
    echo ($a === $c)?1:0; // 输出0
    echo ($b == $c)?1:0; // 输出1
    echo ($b === $c)?1:0; // 输出0
    echo ($a == $d)?1:0; // 输出1
    echo ($a === $d)?1:0; // 输出0 

    2、strrchr函数

    在W3School站点上的注释如下:

    strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。
    如果成失败,否则返回 false。

    实际上,这个函数是查找某个字符,而不是查找字符串,应该参考官方文档

    代码示例:

    [php] view plain copy

    $a = 'abcdef.txt';
    $b = '.php';
    echo strrchr($a, $b);
    上面的代码输出是:.txt

    也就是说,如果$b是字符串,只使用第一个字符,后面的其它字符会忽略

    注:php提供了strstr函数,为什么不提供strrstr函数呢,虽然自己实现也很简单

    3、foreach里的引用赋值,参见官方文档

    这个引用赋值很好哇,对用C#的我,在C#里要修改foreach的元素,是不可能的,是会出异常滴,php把这个变成了可能,但是:
    在官方文档里有一句警告:Warning 数组最后一个元素的 $value 引用在 foreach 循环之后仍会保留。建议使用 unset() 来将其销毁。
    我们看一组代码:

    [php] view plain copy

    $a = [1,2,3];
    foreach($a as &$item){
    echo $item . ',';
    }
    //unset($item); // 引用赋值后不销毁对象
    foreach($a as $item){
    echo $item . ',';
    }
    上面的代码的输出如下:
    1,2,3,1,2,2 看最后一个输出的是2,而不是3,就是因为代码里没有销毁$item造成的,原因如下:
    第一个循环,把3的引用赋给了$item,第二个循环,把1赋给了$item,因为$item是引用,导致数组的元素3变成了1,明白了吗?

    4、isset与empty的联系和区别,isset文档 empty文档
    empty对如下8种情况返回true:
    null、 空串""、字符串0"0"、空array、布尔值false、数字0、浮点数0.0、类里用var定义但是未赋值

    isset 检测变量是否设置,并且不是 NULL,但是对于empty的8种情况,只有null返回false,其它7种情况都返回true

    综上所述,除了empty描述的的非null的7种情况,在其它情况下, if(empty(变量)) 等效于 if(!isset(变量))

    灵活用法一则:直接访问 $arr['aaa'] 可能报错,说aaa不存在,可以用:
    if(isset($arr['aaa']){ 操作代码} 或 if(!empty($arr['aaa']){ 操作代码}

    5、trim函数遇到中文空格时,会乱码

    [php] view plain copy

    $str = '  《前后有全半角空格》  ';
    var_dump($str);
    $str2 = trim($str, '  ');
    var_dump($str2);
    $str3 = mb_ereg_replace('^(?:s| )+|(?:s| )+$', '', $str);
    var_dump($str3);
    $str4 = mb_ereg_replace('^[s ]+|[s ]+$', '', $str);
    var_dump($str4);
    参考如上的代码,输出结果:

    [plain] view plain copy

    string '  《前后有全半角空格》  ' (length=38)
    string '�前后有全半角空格》' (length=28)
    string '《前后有全半角空格》' (length=30)

    A PHP Error was encountered
    Severity: Warning
    Message: mb_ereg_replace(): mbregex compile err: invalid code point value
    可以看出:trim导致乱码出现了,正则^(?:s| )+|(?:s| )+$ 可以正常工作,而正则^[s ]+|[s ]+$却编译异常,原因我还没搜索到


    6、intval在Windows和Centos上,最大值范围不同
    在centos上,intval转换的最大值是9223372036854775807,

    而在我的Win7x64+64位的php上,转换最大值却是2147483647,非常奇怪,手册明明说64位系统都是9223372036854775807,
    这么大一坑啊,官方解释php6以下在win上仅是测试版,不支持64位

    7、mysql字段类型为varchar时,不能用where xx=123来检索,会无法利用索引
    建议所有SQL的值都用单引号括起来,如:where xx='123',如果字段类型为int,也能正确利用索引

    8、执行SQL后不判断返回值,或判断逻辑错误:

    $sql = 'insert into app_log(id) select 0 from dual where 1=2';
    $this->db->query($sql);
    return true; // 不加判断,直接返回true

    $sql = 'insert into app_log(id) select 0 from dual where 1=2';
    $result = $this->db->query($sql);
    if ($result) { // 有bug,插入不成功,result也是true
    return true;
    }
    return false;

    上面的2段代码应该改成:

    $sql = 'insert into app_log(id) select 0 from dual where 1=2';
    $this->db->query($sql);
    // 如果sql有语法问题,affected_rows是-1
    if ($this->db->affected_rows() > 0) {
    return true;
    }
    return false;

    注意:mysql中,update a set name='123' where id=1;
    如果id为1的记录,name已经是123,那么这条update语句的affected_rows()=0

  • 相关阅读:
    删除 AP 发票相关脚本
    js框架简明
    16 款最流行的 JavaScript 框架
    八款你不得不知的开源前端JS框架
    ExtJS面向对象
    js6类和对象
    js模拟类
    js实现继承
    Html中各种空格的显示
    常用快速原型设计工具大比拼、原型设计工具哪个好用
  • 原文地址:https://www.cnblogs.com/Crius/p/13042518.html
Copyright © 2011-2022 走看看