tags:

views:

303

answers:

5

I'm having problems to iterate twice on the same array:

<? $indice=0 ?>
<?php foreach ($comisiones as $comision1):?>  
  <tr>  
    <td><?php echo ++$indice ?></td>  
    <td><?php echo tag('select',array('name'=>'comision_'.$indice),true)?>  
          <?php foreach ($comisiones as $comision2):?>  
            <option value="<?php echo $comision2->getId()?>">
               <?php echo $comision2->getNombre()." - ".$comision2->getDescripcion()?> 
            </option>
          <?php endforeach?> 
        </select>
    </td>
  </tr>
<?php endforeach?>  

The above code prints:

code result

And I'm expecting to see something like this (labels of the combos in the images are not the same, but I think the idea is clear):

expected results

Thanks in advance

+2  A: 

My first instict is don't use foreach loops. I believe that PHP is using some internal pointers so the two foreach loops affect each other's position. Instead use a normal for loop.

LeguRi
Thanks Richard, I replaced the first foreach with a normal for and it worked. I can't believe that PHP has such a HUGE BUG in such a simple structure...
Neuquino
It's not a bug, it's documented as found on php.net/foreach: Note: Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer. Don't rely on the array pointer during or after the foreach without resetting it.
Pim Jager
whether it is documented, it is a BUG. That behavior is not intuitive, no one would expect that result from that piece of code. PHP should use different pointers for each foreach structure.
Neuquino
Sorry Neuquino, I have to agree with Pim Jager, as the `foreach` construct sits on top of the Iterator Pattern. You'd encounter the same behavior in any language which uses `foreach` - it's just become a little obscure as its been a while since any of us has had to manually write a `foreach` the old fashioned way... and even if it was a bug, we're talking about PHP here; I could _easily_ believe that PHP would have such a huge bug :P
LeguRi
+2  A: 

Based on your code it seems like you don't actually want a foreach loop in the outher loop. Just do a regular for loop from 0 to the size of the array. Something like this:

for ($i = 0; $i < count($comisiones); ++$i) {
    // Do what you want
}
alexanderblom
yes, that would be one solution for my code. But I wanted to know I it was not working...
Neuquino
A: 

I belive thet the second loop should looks like or its related to

<?php foreach ($comision1 as $comision2): ?>

not

<?php foreach ($comisiones as $comision2): ?>  

otherwise you are not using $commision1 from first loop anyware

<?php foreach ($comisiones as $comision1): ?>  
Marcin
I'm using it to iterate... it would be the same as a for loop from 1 to count($comisiones)...
Neuquino
A: 

Use normal for loops with two indexes, like this:

$len = count($comisiones);
for($i = 0; $i < $len; ++$i)
   for($j = 0; $j < $len; ++$j)

As stated clearly on PHP website:

"Note: When foreach first starts executing, the internal array pointer is automatically reset to the first element of the array." [source: http://www.php.net/manual/en/control-structures.foreach.php ]

Therefor your inner foreach loop resets every time the array pointer, that's why you are getting out only a terrible mess. :)

Marco Demajo
A: 

I had a similar interesting prob with foreach in an foreach but with not the same Arrays...

Had a Zend MVC, with the controller fetching results fron two tables into two view-variables:

$foodTable = new Table_Food();
$foodTable->select()->where(array('active' => true));

$foodCategoryTable = new Table_FoodCategory();
$foodCategoryTable->select()->order(array('order'));

$food = $foodTable->fetchAll();
$foodCategories = $foodCategoryTable->fetchAll();

$this->view->food = $food;;
$this->view->foodCategories = $foodCategories;

Then the view made two loops, first over the categories and inside over the food, which has everyone a category. If the category-id of the food loop is the category-id of the category loop -> print it to screen...

<?php foreach($this->foodCategories as $foodCategoryKey => $foodCategory) { ?>
  // echo the category header
    <?php foreach($this->food as $foodKey => $food) {
      if($food["food_category_id"] == $foodCategory["id"]){ ?>
        // echo food, food details, price, and so on
      <? }
    }
} ?>

In this version the array-key of the outher loop did not loop from 0 to 5 (like this: 0, 1, 2, 3, 4, 5), but form 0 to 4 (in this way: 0, 2, 4) and said: "I've done it, baby". I had 6 categories (0-Insalate, 1-Pizza, 2-Pasta, 3-Secondi Piati, 4-Desserts, 5-Drinks) and on the screen i got no Pizza, no Secondi piati and no Drinks...

The "step" of the outer loop (known from other programming languages) was 2, not 1 like expected.

I ran out of energy searching for the "why".

Different tables, different variables, different foreach-loops and foreach-params and so on... I tried many things, but always the "step 2" in outer foreach.

The inner loop, printing the food details, always worked normal.

Tried to replace the outher foreach with

for($foodCategoryKey = 0; $foodCategoryKey < count($this->foodCategories); $foodCategoryKey++) { ... }

and everything worked fine.

But not with foreach...

Why, why, why ???

Since I changed the variable-assignment in the controller to:

$this->view->food = $food->toArray();
$this->view->foodCategories = $foodCategories->toArray();

it worked like it should - like the for() - loop ...

Can anybody tell me where the devil in Mrs. Jones is here?

Yours,

Walta

walta