浅谈PHP中关于foreach使用引用变量的坑

 更新时间:2016年11月14日 15:32:07   投稿:jingxian  
下面小编就为大家带来一篇PHP不使用递归的无限级分类的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

写PHP好多年,但仍然会犯低级错误,今天遇到个 foreach中引用变量时的坑,PHP版本为 5.6.12 代码如下:

<?php
$arr = ['a', 'b', 'c', 'd', 'e'];
foreach ($arr as $i=>&$a) {
  $a = $a.'_'. $a;
  echo $a .'<br>';
}
echo '<hr>';
foreach ($arr as $i=>$a) {
  echo $a .'<br>';
}
echo '<hr>';
print_r($arr);

输出结果

一开始看到第二个 foreach 输出的结果感觉很是莫名其妙,怎么会输出两个 d_d 呢?

仔细想了想,原来因为PHP foreach 中的 $a 的作用域是整个函数的局部变量,在循环外部仍然有效,而不是被封闭在循环内的,

所以当执行第二个foreach 时的 $a 并不是新的变量,而是仍然指向 $arr 数组第5个元素的地址引用,

当第二个 foreach 在循环时实际上是在不停的给 $arr 数组的第5个元素赋值,

具体赋值情况,

第一次:a_a 赋值给第5个元素, 结果为: [a_a, b_b, c_c, d_d,a_a]

第二次:b_b 赋值给第5个元素,结果为: [a_a, b_b, c_c, d_d,b_b]

第三次:c_c 赋值给第5个元素,结果为: [a_a, b_b, c_c, d_d,c_c]

第四次:d_d 赋值给第5个元素,结果为: [a_a, b_b, c_c, d_d,d_d]

第五次:此时因为第五个元素已经变成 d_d 又重新把 d_d 赋值给第5个元素,结果还是为: [a_a, b_b, c_c, d_d,d_d]

解决办法:

1.尽量不使用相同的循环变量名;

2.每次使用完或再次使用前进行 unset($a); 处理,解除地址应用

还是用上面代码示例:

$arr = ['a', 'b', 'c', 'd', 'e'];
foreach ($arr as $i=>&$a) {
  $a = $a.'_'. $a;
  echo $a .'<br>';
}
echo '<hr>';
echo $a;
echo '<hr>';

// 这里 unset 掉
unset($a);

echo $a = 'ccc';
echo '<hr>';
print_r($arr);
echo '<hr>';
foreach ($arr as $i=>$a) {
  echo $a .'<br>';
}
echo '<hr>';
print_r($arr);

输出结果:

现在就正常了,这些小细节一定要注意了

以上就是小编为大家带来的浅谈PHP中关于foreach使用引用变量的坑全部内容了,希望大家多多支持脚本之家~

相关文章

  • Laravel实现登录跳转功能

    Laravel实现登录跳转功能

    网站管理员登录成功后跳转到网站后台,vip用户登录成功后跳转到vip页面,跳转功能怎么实现的呢,下面小编给大家带来了Laravel实现登录跳转功能,需要的朋友可以参考下
    2021-08-08
  • 详解PHP的Sodium加密扩展函数

    详解PHP的Sodium加密扩展函数

    Sodium 出现的目的也是为了代替Mcrypt这个原来的加密扩展。在 PHP7.2 之后,Mcrypt已经被移除,在PHP7.1时就已经被标记为过时。不过,Sodium扩展的应用也并不是很多,大部分情况下我们都会使用OpenSSL来进行加密操作,所以,我们这篇文章只做了解即可。
    2021-06-06
  • PHP+Ajax验证码验证用户登录

    PHP+Ajax验证码验证用户登录

    这篇文章主要为大家详细介绍了PHP+AJAX验证码验证用户登录的相关资料
    2016-07-07
  • Laravel 集成微信用户登录和绑定的实现

    Laravel 集成微信用户登录和绑定的实现

    这篇文章主要介绍了Laravel 集成微信用户登录和绑定的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • php 验证码实例代码

    php 验证码实例代码

    首先验证码的原理就是,画一张图片,然后在这张图片上写一些字,然后加一些干扰的线条,像素点之类的东西就ok了,这里要使用php那就要知道php中画图的函数是那些,然后拿来用便是了。
    2010-06-06
  • Yii redis集合的基本使用教程

    Yii redis集合的基本使用教程

    这篇文章主要给大家介绍了关于Yii redis集合的基本使用教程,文中通过示例代码介绍的非常详细,对大家学习或者使用Yii、redis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-06-06
  • ThinkPHP框架实现用户信息查询更新及删除功能示例

    ThinkPHP框架实现用户信息查询更新及删除功能示例

    这篇文章主要介绍了ThinkPHP框架实现用户信息查询更新及删除功能,结合实例形式分析了thinkPHP框架数据库配置、控制与模板调用实现信息查询、更新、删除等功能相关操作技巧,需要的朋友可以参考下
    2018-03-03
  • Laravel事件监听器用法实例分析

    Laravel事件监听器用法实例分析

    这篇文章主要介绍了Laravel事件监听器用法,结合实例形式分析了Laravel事件监听器的注册、使用相关流程及操作技巧,需要的朋友可以参考下
    2019-03-03
  • PHP处理Ajax请求与Ajax跨域问题

    PHP处理Ajax请求与Ajax跨域问题

    这篇文章主要介绍了PHP处理Ajax请求与Ajax跨域问题的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-02-02
  • thinkphp中html:list标签传递多个参数实例

    thinkphp中html:list标签传递多个参数实例

    这篇文章主要介绍了thinkphp中html:list标签传递多个参数的解决方法,在处理参数传递的情况非常具有实用价值,需要的朋友可以参考下
    2014-10-10

最新评论