加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

深入详解PHP中的foreach

发布时间:2022-07-16 15:55:31 所属栏目:PHP教程 来源:互联网
导读:语言基础 foreach 语法结构提供了遍历数组的简单方式。 php5之前, foreach仅能用于数组 php5+, 利用foreach可以遍历对象 foreach仅能够应用于数据和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。 有两种语法: /* 遍历给定的
  语言基础
  foreach 语法结构提供了遍历数组的简单方式。
 
  php5之前, foreach仅能用于数组 php5+, 利用foreach可以遍历对象
 
  foreach仅能够应用于数据和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。
 
  有两种语法:
 
  /*
 
    遍历给定的 array_expression 数据。每次循环中, 当前单元的值被赋给$value并且数组内部的指针向前移一步(因此下次循环中将会得到下一个单元)
 
  */
 
  foreach (array_expression as $value) {
 
  foreach (array_expression as $key => $value) :
 
      // statement
 
  endforeach;
 
  还能够自定义遍历对象!
 
  当foreach开始执行时, 数组内部的指针会自动指向第一个单元. 这意味着不需要在foreach循环之前调用reset()由于foreach依赖内部数组指针, 在循环中修改其值将可能导致意外的行为
 
  可以很容易通过在 $value 之前加上 & 来修改数组元素. 此方法将以引用 赋值, 而不是拷贝一个值.
 
 
  <?php
 
   
 
  $arr = [1, 2, 3, 4];
 
  foreach($arr as &$value) {
 
      $value = $value * 2;
 
  }
 
   
 
  // $arr is now [2, 4, 6, 8]
 
  unset($value); // 最后取消掉引用
 
  $value的引用仅在被遍历的数组可以被引用时才可用(例如是个变量)。
 
  以下代码无法运行:
 
 
  <?php
 
  /*
 
    此段代码可以运行
 
    运行结果:
 
      1-2
 
      2-4
 
      3-6
 
      4-8
 
  */
 
  foreach (array(1, 2, 3, 4) as &$value) {
 
      echo $value, '-';
 
      $value = $value * 2;
 
      echo $value, PHP_EOL;
 
  }
 
  Warning: 数组最后一个元素的 $value 引用在 foreach 循环之后仍会保留。建议使用 unset() 来将其销毁。
 
  Note: foreach 不支持用 @ 来抑制错误信息的能力
 
  foreach 虽然简单, 不过它可能出现一些意外行为, 特别是代码涉及到引用的时候。
 
 
  <?php
 
  $arr = [1, 2, 3];
 
   
 
  foreach ($arr as $k => &$v) {
 
      $v = $v * 2;
 
  }
 
   
 
  foreach ($arr as $k => $v) {
 
      echo $v, PHP_EOL;
 
  }
 
  <?php
 
  foreach ($arr as $k => $v) {
 
      $k = currentKey();
 
      $v = currentVal();
 
      // 继续运行用户代码
 
  }
 
  根据上述理论, 现在我们重新来分析下第一个foreach:
 
  循环 备注 $arr值
  循环 1-1 由于$v是一个引用, 因此 $v = &$arr[0], $v = $v * 2 相当于 $arr[0] * 2 [2, 2, 3]
  循环 1-2 $v = &$arr[1] [2, 4, 3]
  循环 1-3 $v = &$arr[2] [2, 4, 6]
  循环 2-1 隐含操作 $v = $arr[0] 被触发, 由于此时 $v 仍是 $arr[2] 的引用, 相当于 $arr[2] = $arr[0] [2, 4, 2]
  循环 2-2 $v = $arr[1], 即$arr[2] = $arr[1] [2, 4, 4]
  循环 2-3 $v = $arr[2], 即$arr[2] = $arr[2] [2, 4, 4]
  如何解决此类问题呢? PHP手册上有一段提醒:
 
  Warning: 数组最后一个元素的 $value 引用在 foreach 循环之后仍会保留。建议使用 unset() 来将其销毁。
 
 
 
  <?php
 
  $arr = [1, 2, 3];
 
   
 
  foreach ($arr as $k => &$v) {
 
      $v = $v * 2;
 
  }
 
  unset($v);
 
  foreach ($arr as $k => $v) {
 
      echo $v, PHP_EOL;
 
  }
 
  <?php
 
  $arr = ['a', 'b', 'c'];
 
   
 
  foreach ($arr as $k => $v) {
 
      echo key($arr), "=>", current($arr), PHP_EOL;
 
  }
 
   
 
  foreach ($arr as $k => &$v) {
 
      echo key($arr), "=>", current($arr), PHP_EOL;
 
  }
 
  ➜  demo /usr/local/Cellar/php/7.2.7/bin/php -dvld.active=1 a.php
 
  Finding entry points
 
  Branch analysis from position: 0
 
  Jump found. (Code = 77) Position 1 = 2, Position 2 = 15
 
  Branch analysis from position: 2
 
  Jump found. (Code = 78) Position 1 = 3, Position 2 = 15
 
  Branch analysis from position: 3
 
  Jump found. (Code = 42) Position 1 = 2
 
  Branch analysis from position: 2
 
  Branch analysis from position: 15
 
  Jump found. (Code = 62) Position 1 = -2
 
  Branch analysis from position: 15
 
  filename:       /Users/jianyong/demo/a.php
 
  function name:  (null)
 
  number of ops:  17
 
  compiled vars:  !0 = $arr, !1 = $v, !2 = $k
 
  line     #* E I O op                           fetch          ext  return  operands
 
  -------------------------------------------------------------------------------------
 
     2     0  E >   ASSIGN                                                   !0, <array>
 
     4     1      > FE_RESET_R                                       $4      !0, ->15
 
           2    > > FE_FETCH_R                                       ~5      $4, !1, ->15
 
           3    >   ASSIGN                                                   !2, ~5
 
     5     4        INIT_FCALL                                               'key'
 
           5        SEND_VAR                                                 !0
 
           6        DO_ICALL                                         $7
 
           7        ECHO                                                     $7
 
           8        ECHO                                                     '%3D%3E'
 
           9        INIT_FCALL                                               'current'
 
          10        SEND_VAR                                                 !0
 
          11        DO_ICALL                                         $8
 
          12        ECHO                                                     $8
 
          13        ECHO                                                     '%0A'
 
          14      > JMP                                                      ->2
 
          15    >   FE_FREE                                                  $4
 
     7    16      > RETURN                                                   1
 
   
 
  branch: #  0; line:     2-    4; sop:     0; eop:     1; out1:   2; out2:  15
 
  branch: #  2; line:     4-    4; sop:     2; eop:     2; out1:   3; out2:  15
 
  branch: #  3; line:     4-    5; sop:     3; eop:    14; out1:   2
 
  branch: # 15; line:     5-    7; sop:    15; eop:    16; out1:  -2
 
  path #1: 0, 2, 3, 2, 15,
 
  path #2: 0, 2, 15,
 
  path #3: 0, 15,
 
  0=>a
 
  0=>a
 
  0=>a

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读