PHP:多个foreach中的变量范围

时间:2010-12-16 10:35:49

标签: php variables loops scope foreach

编辑:
在函数调用中使用$ i + 1解决了问题。

我在多个foreaches中使用变量时遇到问题。当我尝试在foreach中调用函数时,问题就会出现。每当我这样做时,主循环的迭代器值突然为零(无论它在哪一圈),但是当我注释掉函数调用时,迭代器值会再次显示它。

在以下示例中,有人能指出我正确的方向访问变量:

这应该是正常的

for($i=0; $i<3; $i++)
{
    echo $i; // 1, 2, 3
    foreach($something as $value)
    {
        echo $i; // main loop's iterator value
        foreach($value as $moreSomething)
        {
            echo $i; // main loop's iterator value 
        }
    }
}

但这不起作用,迭代器显示为0。

for($i=0; $i<3; $i++)
{
    echo $i; // 1, 2, 3
    foreach($something as $value)
    {
        echo $i; // 0
        foreach($value as $moreSomething)
        {
            echo $i; // 0
            $object->addStuff($i, $moreSomething); // i = 0, moreSomething is correct
        }
    }
}

编辑: 我正在添加示例代码来重现问题。请注意,这是关于$ i的值的行为,而不是名称的正确顺序或类似的行为。 我只关心为什么$ i的价值会突然改变。可能是我的逻辑,但亲自看看

(当在addName()函数中使用$ i或$ b时,$ i的输出为000000000012,当使用$ a时,$ i的输出突然变为00000000001111111222)

class RockPaperScissors
{
    private $nameArray;

  // constructor
  function RockPaperScissors () 
  {
    $this->nameArray = array();
  }

  function addName($level, $name)
  {
    $this->nameArray[$level][] = $name;
  }

  function getNames($level)
  {
    $array = array();
    foreach ($this->nameArray as $key => $value)
    {
        if ($key == $level)
        {
            foreach ($value as $name)
            {
                $array[] = $name;
            }
        }
    }
    return $array;
  }

  function printArray()
  {
    print_r($this->nameArray);
  }
}

function getNewNames($name)
{
    $array = array();
    switch ($name)
    {
        case "Mickey":
            $array[] = "Morty";
            $array[] = "Ferdie";
            break;

        case "Donald":
            $array[] = "Houie";
            $array[] = "Dewey";
            $array[] = "Louie";
            break;

        case "Goofy":
            $array[] = "Gilbert";
            break;

        case "Morty":
            $array[] = "Morty-B";
            break;

        case "Ferdie":
            $array[] = "Ferdie-B";
            break;

        case "Houie":
            $array[] = "Houie-B";
            break;

        case "Dewey":
            $array[] = "Dewey-B";
            break;

        case "Louie":
            $array[] = "Louie-B";
            break;

        case "Gilbert":
            $array[] = "Gilbert-B";
            break;
    }

    return $array;
}

$MAX_LEVELS = 3;
$RPS = new RockPaperScissors();
$RPS->addName(0, "Mickey");
$RPS->addName(0, "Donald");
$RPS->addName(0, "Goofy");

$a = 0;
$b = 0;
for ($i=0; $i<$MAX_LEVELS; $i++)
{
    $namesFromRPS = $RPS->getNames($i);
    echo $i;
    foreach($namesFromRPS as $name)
    {
        echo $i;
        $newNames = getNewNames($name);
        foreach($newNames as $newName)
        {         
            echo $i;
            // try switching $i to $a or $b and notice the behaviour change of $i
            $RPS->addName($i, $newName);
        }
        $a++;
    }
    $b++;
}

//$RPS->printArray();

6 个答案:

答案 0 :(得分:5)

foreach循环没有自己的范围。

预期这种方式有效:

Set $i to 0
 Enter the first foreach loop with `$i = 0`
  Enter the second foreach loop with `$i = 0`

Set $i to 1
 Enter the first foreach loop with `$i = 1`
  Enter the second foreach loop with `$i = 1`

etc.

我会打赌啤酒循环按预期工作,但当$i到达1时,内循环没有任何关系。

答案 1 :(得分:1)

不是真正的答案,但您的代码实际上与以下内容相同:

foreach($something as $value)
{
    foreach($value as $moreSomething)
    {
        for($i=0; $i<3; $i++)
        {
            $object->addStuff($i, $moreSomething); // i = 0, moreSomething is correct
        }
    }
}

你确定这个逻辑是正确的吗?你想让我做什么?不知道addStuff正在做什么,用另一个索引添加相同的值三次似乎有点奇怪。

以下是方法调用的示例:

$something = array(array(1,2), array(1,2));

class F {
   public function b($i, $value) {
       echo 'In function: i: ' . $i . ' value: ' . $value . PHP_EOL;
   }
}

$f = new F();

for($i=0; $i<3; $i++)
{
    echo "in for: " . $i . PHP_EOL; // 1, 2, 3
    foreach($something as $value)
    {
        echo "in 1. foreach: " . $i . PHP_EOL;
        foreach($value as $moreSomething)
        {
            echo "in 2. foreach: " . $i . PHP_EOL;
            $f->b($i, $moreSomething);

        }
    }
}

打印(按预期):

in for: 0
in 1. foreach: 0
in 2. foreach: 0
In function: i: 0 value: 1
in 2. foreach: 0
In function: i: 0 value: 2
in 1. foreach: 0
in 2. foreach: 0
In function: i: 0 value: 1
in 2. foreach: 0
In function: i: 0 value: 2
in for: 1
in 1. foreach: 1
in 2. foreach: 1
In function: i: 1 value: 1
in 2. foreach: 1
In function: i: 1 value: 2
in 1. foreach: 1
in 2. foreach: 1
In function: i: 1 value: 1
in 2. foreach: 1
In function: i: 1 value: 2
in for: 2
in 1. foreach: 2
in 2. foreach: 2
In function: i: 2 value: 1
in 2. foreach: 2
In function: i: 2 value: 2
in 1. foreach: 2
in 2. foreach: 2
In function: i: 2 value: 1
in 2. foreach: 2
In function: i: 2 value: 2

所以错误必须在其他地方

答案 2 :(得分:0)

我不确定,但它可能与在$i循环中定义for()的事实有关。我会在定义$i循环之前尝试定义for()

詹姆斯

答案 3 :(得分:0)

在第二个示例中,$i 对于基本循环的第一次迭代将为0。

对于所有$something和所有$value,它将保持设置为0,然后它将继续进行下一个基本迭代,将$i设置为1,依此类推。

答案 4 :(得分:0)

我将变量$something添加为2d数组

$something = Array(1 => Array(1 => "1", 2 => "2"), 2 => Array(3 => "3", 4 => "4"))

使用它,你的foreach显示得很好:

000000011111112222222

答案 5 :(得分:0)

<?php

$something = array(
    "one"   => array("oneMore1", "oneMore2", "oneMore3"),
    "two"   => array("twoMore1", "twoMore2", "twoMore3"),
    "three" => array("thrMore1", "thrMore2", "thrMore3"));

for($i = 0; $i < 3; $i++)
{
    echo "FIRST LOOP: " . $i;
    echo "\n";
    foreach($something as $value)
    {
        echo "SECOND LOOP: " . $i;
        echo "\n";
        foreach($value as $moreSomething)
        {
            echo "THIRD LOOP: " . $i;
            echo "\n";
            //$object->addStuff($i, $moreSomething);
        }
    }
}

我发现此处执行此代码没有问题:http://www.ideone.com/HsVDj