foreach的一些小坑

PHP-foreach的一些小坑

再PHP中,foreach是对数组遍历的一个方法,遍历也只用于数组,在编程的时候有一些小坑,记录如下。

foreach的两种语法结构

  1. 只遍历引用值:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    foreach (array_expression as $value)
      statement

    //示例:
    <?php
    $arr = array(1, 2, 3, 4);
    foreach ($arr as $value) {
    echo $value;
    }
    echo "\n";
    echo $value;
    ?>
    //显示结果:
    1234
    4
  2. 遍历引用键和值:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    foreach (array_expression as $key => $value)
       statement
      
    //示例:
    <?php
    $arr = array(1, 2, 3, 4);
    foreach ($arr as $key => $value) {
    echo "[$key] => $value\n";
    }
    echo "\n";
    echo "[$key] => $value";
    echo "\n";
    ?>

    //结果:
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4

    [3] => 4

在foreach中是否使用&的区别:

  1. 不使用&,foreach的作用域只在当前循环中,不会改变外部数组的值:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <?php
    $arr = array(1, 2, 3, 4);
    foreach ($arr as $value) {
    $value = $value * 2;
    echo "$value ";
    }

    echo "\n";
    print_r($arr);

    //结果:
    2 4 6 8
    Array
    (
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    )
  2. 使用&会使得作用域扩大到对应的数组,改变数组的值:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <?php
    $arr = array(1, 2, 3, 4);
    foreach ($arr as &$value) {
    $value = $value * 2;
    echo "$value ";
    }

    echo "\n";
    print_r($arr);

    //结果:
    2 4 6 8
    Array
    (
    [0] => 2
    [1] => 4
    [2] => 6
    [3] => 8
    )

在foreach中是否使用&的坑点:

  1. 这里和上面的作用域联系起来,没使用以后不会影响数组本身,所以两次foreach的结果互不影响:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?php
    $arr = array(1, 2, 3, 4);
    foreach ($arr as $value) {
    // $value = $value * 2;
    echo "$value ";
    }
    echo "\n";
    echo $value;
    echo "\n";
    foreach ($arr as $value) {
    echo "$value ";
    }
    echo "\n";
    echo $value;

    //结果

    1 2 3 4
    4
    1 2 3 4
    4
  2. 使用以后改变了作用域,这里&指向第一次foreach的最后一个地址,在PHP中它不会自动释放该地址:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <?php
    $arr = array(1, 2, 3, 4);
    foreach ($arr as &$value) {
    // $value = $value * 2;
    echo "$value ";
    }
    echo "\n";
    echo $value;
    echo "\n";
    foreach ($arr as $value) {
    echo "$value ";
    }
    echo "\n";
    echo $value;

    //结果:
    1 2 3 4
    4
    1 2 3 3
    3
  3. 查看它每次具体的变化:(这里可以验证每次改变的是&指向的最后一个地址)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    <?php
    $arr = array(1, 2, 3, 4);
    foreach ($arr as &$value) {}
    ;
    print_r($arr);

    foreach ($arr as $key => $value) {
    echo "{$key} => {$value} ";
    print_r($arr);
    }
    ?>
    //结果:
    Array
    (
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    )
    0 => 1 Array
    (
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 1
    )
    1 => 2 Array
    (
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 2
    )
    2 => 3 Array
    (
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 3
    )
    3 => 3 Array
    (
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 3
    )
  4. 解决方法:在每次foreach后unset解除&的指定关系,或者在每次遍历中使用不同的变量名:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <?php
    $arr = array(1, 2, 3, 4);
    foreach ($arr as &$value) {
    echo "$value ";
    }
    unset($value);
    echo "\n";
    foreach ($arr as $value) {
    echo "$value ";
    }
    ?>

    //结果:
    1 2 3 4
    1 2 3 4

    //使用不同的变量名
    <?php
    $arr = array(1, 2, 3, 4);
    foreach ($arr as &$value) {
    echo "$value ";
    }
    echo "\n";
    foreach ($arr as $val) {
    echo "$val ";
    }
    ?>
    //结果:
    1 2 3 4
    1 2 3 4