У меня есть несколько запросов об изменении массива во время цикла foreach(). В приведенном ниже коде я просматриваю три массива, которые содержат замыкания/обратные вызовы и вызывают их. Я добавляю замыкание в конец каждого массива во время итерации, однако иногда foreach(), похоже, не распознает, что массив изменил размер, и поэтому закрытое закрытие не вызвано.
class Foo
{
private $a1 = array();
private $a2 = array();
public function f()
{
echo '<pre style="font-size: 20px;">';
echo 'PHP: ' . phpversion() . '<br><br>';
$this->a1[] = function() { echo 'a1 '; };
$this->a1[] = array($this, 'g');
foreach ($this->a1 as &$v)
{
// The callback added in g() never gets called.
call_user_func($v);
//echo 'count(v) = ' . count($v) . ' ';
}
echo '<br>';
// The same thing works fine with a for() loop.
$this->a2[] = function() { echo 'a2 '; };
$this->a2[] = array($this, 'h');
for ($i = 0; $i < count($this->a2); ++$i)
call_user_func($this->a2[$i]);
echo '<br>';
// It also works fine using a local array as long as it
// starts off with more than one element.
$a3[] = function() { echo 'a3 '; };
//$a3[] = function() { echo 'a3 '; };
$i = 0;
foreach ($a3 as &$x)
{
call_user_func($x);
if ($i++ > 1) // prevent infinite loop
break;
// Why does this get called only if $a3 originally starts
// with more than one element?
$a3[] = function() { echo 'callback '; };
}
echo '</pre>';
}
private function g()
{
echo 'g() ';
$this->a1[] = function() { echo 'callback '; };
}
private function h()
{
echo 'h() ';
$this->a2[] = function() { echo 'callback '; };
}
}
$foo = new Foo;
$foo->f();
Вывод:
PHP: 5.3.14-1~dotdeb.0
a1 g()
a2 h() callback
a3
Ожидаемый результат:
a1 g() callback
a2 h() callback
a3 callback
Вывод для $a3
, если я раскомментирую второй элемент перед циклом:
a3 a3 callback
- Почему первый цикл
foreach ($this->a1 as &$v)
не реализует$v
имеет другой элемент для итерации? - Почему модификация
$a3
работает во время третьего циклаforeach ($a3 as &$x)
, но только когда массив начинается с более чем одного элемента?
Я понимаю, что изменение массива во время итерации, вероятно, не очень хорошая идея, но поскольку PHP, похоже, позволяет это мне любопытно, почему это работает так, как это делается.