php foreach工作原理,PHP foreach原理详解

当 foreach 开始执行时,数组内部的指针会自动指向第一个单元。如果移动指针的结果超出了数组单元的末端,则退出循环。

例子:

$array = [

'name' => 'Jobs',

'age' => 50,

];

foreach ($array as $key => $value) {

$value = 22;

//赋值,但是没有影响到$array[$key]位置的值,除非加上 $array[$key] = $value;

}

上面的foreach 对数组内的值没影响。有时候我们为了在循环过程中改变数组项的值,在foreach的时候变量入口可以加个&符号,表示,循环过程中使用数组中原来的值,而不是一个复制的值,如

$array = [

'name' => 'Jobs',

'age' => 50,

];

foreach ($array as $key => &$value) {

//直接改变数组$array[$key]位置的值

$value = 22;

}

结果输出对比:

Array

(

[name] => Jobs

[age] => 50

)

Array

(

[name] => 22

[age] => 22

)

原因分析:

$key和$value都是临时变量,foreach的时候,把每个数组单元的键分别赋值给$key,把每个数组单元的值分别赋给$value,相等于$value=$arr[$key],$value=2仅仅是改变了$value的值(非&传递),并不会影响到$array[$key],自然也就不会影响到$array。

而用第二种方法(引用)的时候,相等于$value=&$array[$key],$array[$key]和$value指向同一内存地址,$value=2自然就改变了$array[$key]的值,也就改变了$array的值

循环时,$key和$value都是临时变量,只是赋值方式不同

陷阱

陷阱:两次循环使用同样的临时变量的情况下,如果第一次循环使用的是引用,那么在第二次循环中即使没有加&符号,临时变量也是引用。这个引用指向了数组中最后一个元素(循环到了最后一个元素结束)。

如:

array = [

'name' => 'php',

'age' => 123,

];

//标记为循环1:

foreach ($array as $key => &$value) {

echo "key=$key, value=$value" . PHP_EOL;

}

//循环完后,最后一个元素 $value = &$array['age'], 这里$value 和 $array['age'] 是引用关系,都是指向的同一个空间。

var_dump($array);

输出结果如下:

array(2) {

["name"]=>

string(3) "php"

["age"]=>

&int(123)

}

//标记为循环2:

foreach ($array as $key => $value) {

//第一次循环进来 $value=$array['name'],此时$value = 'php',由于我们开始的引用中,

$value 和 $array['age'] 建立了引用,所以这里改变了$value的值,

其实就改变了 $array['name']的值,所以 $array['name'] = 'php',

//以后的每次循环处理都和上面第一次相同

//得到的结果:其实每次循环赋值给$value的值,都是给“标记为循环1”中的最后一个元素在赋值,也就是说数组中最后一个元素的值 = 数组中的倒数第2个元素的值

echo "key=$key, value=$value" . PHP_EOL;

}

上面的 foreach循环中输出结果如下:

key=name, value=php

key=age, value=123

key=name, value=php

key=age, value=php

总结:两次循环使用同样的临时变量的情况下,如果第一次循环使用的是引用,那么在第二次循环中即使没有加&符号,临时变量也是引用。这个引用指向了数组中最后一个元素(循环到了最后一个元素结束)。,得到的最后数据结果就是数组中最后一个元素的值 = 数组中的倒数第2个元素的值 (也就是说,最后2个元素的值相同,且为到倒数第2个元素的处理值)。

如何避免这个陷阱呢?

方法1:在第二次循环之前,unset($value)

方法2:第二次foreach的时候使用不同名字的临时变量

扩:

另:查看一个变量是否是引用可以使用xdebug_debug_zval函数(需要有xdebug扩展)。

xdebug_debug_zval的结果形如: value: (refcount=2, is_ref=1)=123

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值