Skip to content

Instantly share code, notes, and snippets.

@vertexvaar
Last active January 4, 2019 11:17
Show Gist options
  • Select an option

  • Save vertexvaar/aa6daba506130c3d19627fcbf720aa0f to your computer and use it in GitHub Desktop.

Select an option

Save vertexvaar/aa6daba506130c3d19627fcbf720aa0f to your computer and use it in GitHub Desktop.
You might not know this about PHP!
<?php
/* Classes implementing iterators can not be used for nested iterating without ugly side effects.
* Iterations over arrays create copies of the arrays with seperate array pointers.
* Iterations over Iterater will only call the object which does not know in which loop it get's called and can not create a second or third pointer on the array for nested iterating.
* To dodge this we must use the array. If the iterator implements a toArray method we're fine. If not, we still can use iterator_to_array().
*/
// Expected
$arr = [
'alpha',
'beta',
'gamma',
];
echo '------------------' . PHP_EOL;
foreach ($arr as $char) {
foreach ($arr as $char1) {
echo $char1 . PHP_EOL;
}
echo $char . PHP_EOL;
}
echo '------------------' . PHP_EOL;
// OUTPUT:
/*
------------------
alpha
beta
gamma
alpha
alpha
beta
gamma
beta
alpha
beta
gamma
gamma
------------------
*/
// Actual
class Collection implements Iterator
{
protected $arr = [
'alpha',
'beta',
'gamma',
];
public function current() { return current($this->arr); }
public function next() { next($this->arr); }
public function key() { return key($this->arr); }
public function valid() { return key($this->arr) !== null; }
public function rewind() { reset($this->arr); }
public function toArray() { return $this->arr; }
}
$coll0 = new Collection();
echo '------------------' . PHP_EOL;
foreach ($coll0 as $char) {
foreach ($coll0 as $char1) {
echo $char1 . PHP_EOL;
}
echo $char . PHP_EOL;
}
echo '------------------' . PHP_EOL;
// OUTPUT
/*
------------------
alpha
beta
gamma
alpha
------------------
*/
/*
* HOW TO DODGE
*/
// Possibility 1: Cloning
foreach (clone $collection as $char) {
foreach (clone $collection as $char1) {
echo $char1 . PHP_EOL;
}
echo $char . PHP_EOL;
}
// Possibility 2: Accessing the array
foreach ($collection->toArray() as $char) {
foreach ($collection->toArray() as $char1) {
echo $char1 . PHP_EOL;
}
echo $char . PHP_EOL;
}
// Possibility 3: Get an array copy with iterator_to_array
$array = iterator_to_array($collection);
foreach ($array as $char) {
foreach ($array as $char1) {
echo $char1 . PHP_EOL;
}
echo $char . PHP_EOL;
}
// OUTPUT of the possibilities above:
/*
------------------
alpha
beta
gamma
alpha
alpha
beta
gamma
beta
alpha
beta
gamma
gamma
------------------
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment