We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

[Volt] nested for loop incorrect behavior

I create simple for loop:

// controller:
$properties = Properties::find(['order' => 'sort_id']);
$this->view->setVar('properties', $properties);

//view:
{% for property in properties %}
    1st loop index - {{ loop.index }}
{% endfor %}

//output:
1st loop index - 1                         
1st loop index - 2

That's ok. Than I added nested loop:

//view:
{% for property in properties %}
    1st loop index - {{ loop.index }}
    {% for _property in properties %}
        2st loop index - {{ loop.index }}
    {% endfor %}
{% endfor %}

//output:
1st loop index - 1
    2st loop index - 1                                
    2st loop index - 2  

1st loop was executed only 1 time. What I'm doing wrong?

This dosen't work in controller too:

$properties = Properties::find(['order' => 'sort_id']);

foreach ($properties as $property) {
    echo '1st ' . $property->id . PHP_EOL;
    foreach ($properties as $p) {
        echo '2nd ' . $p->id . PHP_EOL;
    }
}

//output:
1st 4
2nd 4
2nd 3

Fix:

        foreach ($properties as $property) {
            $key = $properties->key();
            echo '1st ' . $property->id . PHP_EOL;
            foreach ($properties as $p) {
                echo '2nd ' . $p->id . PHP_EOL;
            }
            $properties->seek($key);
        }

//output:
1st 4
2nd 4
2nd 3
1st 3
2nd 4
2nd 3

I think it's a bug in Phalcon\Mvc\Model\Resultset\Simple, no?

Phalcon\Mvc\Model\Resultset\Simple introduces his own iterator. The problem is you are iterating same variable in two loops. When doing this here:

foreach ($properties as $property) {
    echo '1st ' . $property->id . PHP_EOL;
    foreach ($properties as $p) {
        echo '2nd ' . $p->id . PHP_EOL;
    }
}

In first loop you are selecint item 1 from $properties, then in next loop you are selecting item 2 from $properties, then item erd from properties in parent loop etc. Then i guess loop ends. I woul recommend just to clone result to another variable so you don't have any problem.



3.7k
edited May '16

I woul recommend just to clone result to another variable so you don't have any problem.

Like this?

$this->view->setVar('properties', $properties);
$this->view->setVar('_properties', clone $properties);

Maybe will be better fix own iterator?

Im not sure if this can be fixed.



12.2k

This is not a bug in my opinion, just normal behaviour.



3.7k

This is not a bug in my opinion, just normal behaviour.

        $test = (object) [1,2];

        foreach ($test as $i) {
            var_dump('1st - ' . $i);
            foreach ($test as $k) {
                var_dump('2nd - ' . $k);
            }
        }

// output:
string '1st - 1' (length=7)
string '2nd - 1' (length=7)
string '2nd - 2' (length=7)
string '1st - 2' (length=7)
string '2nd - 1' (length=7)
string '2nd - 2' (length=7)

This is normal behaviour.



3.7k

Can I create issue on github?

edited May '16

As i wrote earlier. It's not a bug. Resultset introduces own iterator. If you iterating through it uses it, that's why if you iterating the same object in two loops this weird things happens. Here:

        $test = (object) [1,2];

        foreach ($test as $i) {
            var_dump('1st - ' . $i);
            foreach ($test as $k) {
                var_dump('2nd - ' . $k);
            }
        }

// output:
string '1st - 1' (length=7)
string '2nd - 1' (length=7)
string '2nd - 2' (length=7)
string '1st - 2' (length=7)
string '2nd - 1' (length=7)
string '2nd - 2' (length=7)

You don't have your own iterator, that's why it works.