1

EDIT:
Problem solved by using $i+1 in function call.

I have trouble using variables in multiple foreaches. The problem commeth when I try to call a function inside foreach. Whenever I do this the main loop's iterator value is suddenly zero (no matter which lap it's on) but when I comment out the function call the iterator value shows as it should again.

Could someone point me to the right direction in accessing variables in following examples:

This works as it shoulds

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 
        }
    }
}

But this doesn't work, iterator shows up as a 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
        }
    }
}

EDIT: I'm adding example code to reproduce the problem. Note that this is about the behaviour of $i's value, not the correct order of the names or something like that. I'm just concerned as why the $i's value suddenly changes. Might be my logic, but see for yourself

(when using $i or $b in addName() function $i's output is 000000000012, when using $a then $i's output suddenly changes to 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();
7
  • So you get an output of 1, 2, 3, 0, 0? That would be very odd, and hard to believe. Commented Dec 16, 2010 at 10:37
  • You are effectively calling $object->addStuff($i, $moreSomething); for each $moreSomehting three times, every time with a different $i. Maybe you logic is wrong. What do you want to achieve? Commented Dec 16, 2010 at 10:47
  • Could you show what addStuff is doing? Commented Dec 16, 2010 at 11:02
  • @pekka the output is more like 0000000000012 when it doesn't work and 0000000000111112222222 when it works. examples are a bit simplified, I'm sorry but I can show the whole code, but I could write up something to reproduce it. the addStuff only adds the value to object's private array with $this->arrayname[] = $moreSomething. Commented Dec 16, 2010 at 11:14
  • 0000000000111112222222?? If it would work, every number should as often as the others. 1 seems to appear less often. Commented Dec 16, 2010 at 11:21

6 Answers 6

5

foreach loops do not have their own scope.

The way this is expected to work is:

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'll bet a beer that the loops work as expected, but there is nothing to do for the inner loops when $i reaches 1.

Sign up to request clarification or add additional context in comments.

1 Comment

My head is still a bit fuzzy of all the loop rotations, but I'm fairly sure that this is the case. thanks :P
1

Not a real answer, but your code is actually the same as:

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

Are you sure this logic is correct? What do you want to do? Not knowing what addStuff is doing, it seems a bit odd to add the same value three times with another index to something.

Here is an example with a method call:

$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);

        }
    }
}

which prints (as expected):

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

So the error must be somewhere else.

Comments

0

In your second example, $i will be 0 for the first iteration of the base loop.

It will stay set to 0 for all $somethings and all $values, then it will move on to the next base iteration, setting $i to 1 and so on...

1 Comment

yes that's what it should do, but it stay's as 0 whatever the base loop's iteration is. when the base iteration's count goes to 1 the iterator in foreaches still stays as 0 and that's the problem. this occurs ONLY when I try to use it in a function.
0

i added your variable $something as a 2d Array

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

Using this, your foreach shows just fine:

000000011111112222222

Comments

0

I'm not sure, but it could be something to do with the fact that $i is defined within the for() loop. I'd try defining $i just before the for() loop is defined.

James

2 Comments

Nope, this will have no effect. $i is defined in the for loop, that is enough
This doesn't help. I've tried using $a = 0; before the base for-loop and ++'ing it at the end of the base loop, but it aswell shows as 0
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);
        }
    }
}

I see no problem executing this code here: http://www.ideone.com/HsVDj

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.