【问题标题】:PHP: variable scope in multiple foreachPHP:多个foreach中的变量范围
【发布时间】:2011-05-26 11:28:11
【问题描述】:

编辑:
在函数调用中使用 $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();

【问题讨论】:

  • 所以你得到1, 2, 3, 0, 0的输出?那会很奇怪,很难相信。
  • 您有效地为每个$moreSomehting 调用$object-&gt;addStuff($i, $moreSomething); 三次,每次都使用不同的$i。也许你的逻辑是错误的。你想达到什么目标?
  • 你能告诉我addStuff在做什么吗?
  • @pekka 当它不工作时输出更像 0000000000012 和 0000000000111112222222 当它工作时。例子有点简化,对不起,我可以展示整个代码,但我可以写一些东西来重现它。 addStuff 仅使用 $this->arrayname[] = $moreSomething 将值添加到对象的私有数组中。
  • 0000000000111112222222??如果可行,每个数字都应该和其他数字一样频繁。 1 似乎不常出现。

标签: php variables loops scope foreach


【解决方案1】:

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 时,内部循环无事可做。

【讨论】:

  • 我的头对所有的循环旋转仍然有点模糊,但我很确定情况就是这样。谢谢:P
【解决方案2】:

不是一个真正的答案,但你的代码实际上是一样的:

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

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

下面是一个方法调用的例子:

$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

所以错误一定在其他地方

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 是的,这就是它应该做的,但无论基本循环的迭代是什么,它都保持为 0。当基本迭代的计数变为 1 时,foreaches 中的迭代器仍保持为 0,这就是问题所在。仅当我尝试在函数中使用它时才会发生这种情况。
    【解决方案4】:

    我将您的变量 $something 添加为二维数组

    $something = Array(1 =&gt; Array(1 =&gt; "1", 2 =&gt; "2"), 2 =&gt; Array(3 =&gt; "3", 4 =&gt; "4"))

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

    000000011111112222222
    

    【讨论】:

      【解决方案5】:

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

      詹姆斯

      【讨论】:

      • 不,这不会有任何效果。 $i 在 for 循环中定义,就够了
      • 这没有帮助。我试过使用 $a = 0;在基本 for 循环之前并在基本循环结束时 ++'ing 它,但它也显示为 0
      【解决方案6】:
      <?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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 2018-08-05
        • 1970-01-01
        • 2010-12-19
        • 2011-05-21
        • 2013-07-28
        相关资源
        最近更新 更多