foreach遍历数组的值时用”引用变量“遍历时的一个问题处理

本文讲述了PHP开发者遇到的常见警告——'Cannot use a scalar value as an array',原因在于使用引用变量时的不当操作。通过实例解析,作者揭示了如何避免这种错误并介绍了PHP引用变量的工作原理。

今两天看日志,总发现一个PHP报错:

 

PHP Warning:  Cannot use a scalar value as an array in

这个报错是説原来不是一个数组的值后来又把他当成数组来使用就会报这个错,查了好几个小时终于找到了原来,原来我在遍历数组时,用了&取地址(引用符):
 

foreach ($goods as $k=>&$v) {
    $v['order_id'] = $v['order_id'];
    //..........
    //..........
    $newdb->autoExecute("order_goods", $v, "INSERT");
}

在遍历完成后,又遍历了一个新数组:
 

foreach ($arr_pjgids as $v) {
        $str_pjgids .= $str_pjgids == '' ? intval($v) : ',' . intval($v);
    }

在第一次遍历时,$arr_pjgids的每一项是数值,把把原来的goods的对应的引用地址变量覆盖,导到$goods的最后一项值变成了一个单个值了,导致后续再使用时会出现把值当成数组使用的情况

优化方法就是在遍历使用时定义一个和后面的代码不冲突的值就可以了

foreach ($goods as $kkk=>&$vvv) {
    $vvv['order_id'] = $vvv['order_id'];
    //..........
    //..........
    $newdb->autoExecute("order_goods", $vvv, "INSERT");
}

这样就不会再报

PHP Warning:  Cannot use a scalar value as an array in

报这个错的根本原因就是:

PHP需要注意的是类型的转换:
如果一个变量名(如a)已经被定义为非数组类型,例如integer,那么a可以被转为floating point、string(甚至是object类型),但不可以是数组,即a[0]=1;是错误的,php会报出这样的警告“Cannot use a scalar value as an array“。即使a被定义为一维数组,也不能转为高维数组

这个问题隐藏的很深,加了很多行日志才定位到这个bug,这个问题的出现方式太令我意义了,所以大家在PHP使用引用变量是还是得小心,引用的数据可能会无意的被后面的代码污染

同时也在这里介绍一下PHP引用变量的使用:

引用变量:在PHP中,不同的变量名字访问同一个变量的内容,成为引用,用&符号表示

官方给的解释是:用不一样的名字访问同一个变量内容

var_dump('定义变量a前占用的内存:'.memory_get_usage().'<br />');
$a=range(0,50000,1);
var_dump('定义变量a后占用的内存:'.memory_get_usage().'<br />');
$b = $a;
$b[0] =1;
var_dump('定义变量b后占用的内存:'.memory_get_usage().'<br />');
$c = &$a;
$c[0] =1;
var_dump('定义变量c后占用的内存:'.memory_get_usage().'<br />');
unset($c);
var_dump('销毁变量c后占用的内存:'.memory_get_usage().'<br />');
unset($b);
var_dump('销毁变量b后占用的内存:'.memory_get_usage().'<br />');

关于PHP引用传值和普通传的区别我们可以用上面的代码测试一下:

定义变量a前占用的内存:666984
" string(45) "定义变量a后占用的内存:2768312
" string(45) "定义变量b后占用的内存:4869640
" string(45) "定义变量c后占用的内存:4869664
" string(45) "销毁变量c后占用的内存:4869664
" string(45) "销毁变量b后占用的内存:2768336
"

变量b是普通传值,内存增加很大

变量c是引用传值,内存没太大变化

销毁c后内存没太大变化

销毁b后内存变化很大

都深刻的反应了普通传值和引用传值的区别

有一点我为什么要加两行

$b[0] =1;


$c[0] =1;

是php7有一项技术copy on write(写时复制)机制是在写这个新定义的变量才会真实的分配这个变量的空间,加上了才会看到真实的内存变化

如有问题,欢迎大家留言沟通,点赞支持!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

phpgolife

您的支持是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值