1--TEST-- 2foreach with iteratorAggregate 3--FILE-- 4<?php 5class EnglishMealIterator implements Iterator { 6 private $pos=0; 7 private $myContent=array("breakfast", "dinner", "tea"); 8 9 public function valid() { 10 global $indent; 11 echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; 12 return $this->pos < count($this->myContent); 13 } 14 15 public function next() { 16 global $indent; 17 echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; 18 $this->pos++; 19 } 20 21 public function rewind() { 22 global $indent; 23 echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; 24 $this->pos=0; 25 } 26 27 public function current() { 28 global $indent; 29 echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; 30 return $this->myContent[$this->pos]; 31 } 32 33 public function key() { 34 global $indent; 35 echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; 36 return "meal " . $this->pos; 37 } 38 39} 40 41class FrenchMealIterator implements Iterator { 42 private $pos=0; 43 private $myContent=array("petit dejeuner", "dejeuner", "gouter", "dinner"); 44 45 public function valid() { 46 global $indent; 47 echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; 48 return $this->pos < count($this->myContent); 49 } 50 51 public function next() { 52 global $indent; 53 echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; 54 $this->pos++; 55 } 56 57 public function rewind() { 58 global $indent; 59 echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; 60 $this->pos=0; 61 } 62 63 public function current() { 64 global $indent; 65 echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; 66 return $this->myContent[$this->pos]; 67 } 68 69 public function key() { 70 global $indent; 71 echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; 72 return "meal " . $this->pos; 73 } 74 75} 76 77 78Class EuropeanMeals implements IteratorAggregate { 79 80 private $storedEnglishMealIterator; 81 private $storedFrenchMealIterator; 82 83 public function __construct() { 84 $this->storedEnglishMealIterator = new EnglishMealIterator; 85 $this->storedFrenchMealIterator = new FrenchMealIterator; 86 } 87 88 public function getIterator() { 89 global $indent; 90 echo "$indent--> " . __METHOD__ . "\n"; 91 92 //Alternate between English and French meals 93 static $i = 0; 94 if ($i++%2 == 0) { 95 return $this->storedEnglishMealIterator; 96 } else { 97 return $this->storedFrenchMealIterator; 98 } 99 } 100 101} 102 103$f = new EuropeanMeals; 104var_dump($f); 105 106echo "-----( Simple iteration 1: )-----\n"; 107foreach ($f as $k=>$v) { 108 echo "$k => $v\n"; 109} 110echo "-----( Simple iteration 2: )-----\n"; 111foreach ($f as $k=>$v) { 112 echo "$k => $v\n"; 113} 114 115 116$indent = " "; 117echo "\n\n\n-----( Nested iteration: )-----\n"; 118$count=1; 119foreach ($f as $k=>$v) { 120 echo "\nTop level " . $count++ . ": \n"; 121 echo "$k => $v\n"; 122 $indent = " "; 123 foreach ($f as $k=>$v) { 124 echo " $k => $v\n"; 125 } 126 $indent = " "; 127} 128 129 130?> 131===DONE=== 132--EXPECTF-- 133object(EuropeanMeals)#%d (2) { 134 ["storedEnglishMealIterator":"EuropeanMeals":private]=> 135 object(EnglishMealIterator)#%d (2) { 136 ["pos":"EnglishMealIterator":private]=> 137 int(0) 138 ["myContent":"EnglishMealIterator":private]=> 139 array(3) { 140 [0]=> 141 string(9) "breakfast" 142 [1]=> 143 string(6) "dinner" 144 [2]=> 145 string(3) "tea" 146 } 147 } 148 ["storedFrenchMealIterator":"EuropeanMeals":private]=> 149 object(FrenchMealIterator)#%d (2) { 150 ["pos":"FrenchMealIterator":private]=> 151 int(0) 152 ["myContent":"FrenchMealIterator":private]=> 153 array(4) { 154 [0]=> 155 string(14) "petit dejeuner" 156 [1]=> 157 string(8) "dejeuner" 158 [2]=> 159 string(6) "gouter" 160 [3]=> 161 string(6) "dinner" 162 } 163 } 164} 165-----( Simple iteration 1: )----- 166--> EuropeanMeals::getIterator 167--> EnglishMealIterator::rewind (0) 168--> EnglishMealIterator::valid (0) 169--> EnglishMealIterator::current (0) 170--> EnglishMealIterator::key (0) 171meal 0 => breakfast 172--> EnglishMealIterator::next (0) 173--> EnglishMealIterator::valid (1) 174--> EnglishMealIterator::current (1) 175--> EnglishMealIterator::key (1) 176meal 1 => dinner 177--> EnglishMealIterator::next (1) 178--> EnglishMealIterator::valid (2) 179--> EnglishMealIterator::current (2) 180--> EnglishMealIterator::key (2) 181meal 2 => tea 182--> EnglishMealIterator::next (2) 183--> EnglishMealIterator::valid (3) 184-----( Simple iteration 2: )----- 185--> EuropeanMeals::getIterator 186--> FrenchMealIterator::rewind (0) 187--> FrenchMealIterator::valid (0) 188--> FrenchMealIterator::current (0) 189--> FrenchMealIterator::key (0) 190meal 0 => petit dejeuner 191--> FrenchMealIterator::next (0) 192--> FrenchMealIterator::valid (1) 193--> FrenchMealIterator::current (1) 194--> FrenchMealIterator::key (1) 195meal 1 => dejeuner 196--> FrenchMealIterator::next (1) 197--> FrenchMealIterator::valid (2) 198--> FrenchMealIterator::current (2) 199--> FrenchMealIterator::key (2) 200meal 2 => gouter 201--> FrenchMealIterator::next (2) 202--> FrenchMealIterator::valid (3) 203--> FrenchMealIterator::current (3) 204--> FrenchMealIterator::key (3) 205meal 3 => dinner 206--> FrenchMealIterator::next (3) 207--> FrenchMealIterator::valid (4) 208 209 210 211-----( Nested iteration: )----- 212 --> EuropeanMeals::getIterator 213 --> EnglishMealIterator::rewind (3) 214 --> EnglishMealIterator::valid (0) 215 --> EnglishMealIterator::current (0) 216 --> EnglishMealIterator::key (0) 217 218Top level 1: 219meal 0 => breakfast 220 --> EuropeanMeals::getIterator 221 --> FrenchMealIterator::rewind (4) 222 --> FrenchMealIterator::valid (0) 223 --> FrenchMealIterator::current (0) 224 --> FrenchMealIterator::key (0) 225 meal 0 => petit dejeuner 226 --> FrenchMealIterator::next (0) 227 --> FrenchMealIterator::valid (1) 228 --> FrenchMealIterator::current (1) 229 --> FrenchMealIterator::key (1) 230 meal 1 => dejeuner 231 --> FrenchMealIterator::next (1) 232 --> FrenchMealIterator::valid (2) 233 --> FrenchMealIterator::current (2) 234 --> FrenchMealIterator::key (2) 235 meal 2 => gouter 236 --> FrenchMealIterator::next (2) 237 --> FrenchMealIterator::valid (3) 238 --> FrenchMealIterator::current (3) 239 --> FrenchMealIterator::key (3) 240 meal 3 => dinner 241 --> FrenchMealIterator::next (3) 242 --> FrenchMealIterator::valid (4) 243 --> EnglishMealIterator::next (0) 244 --> EnglishMealIterator::valid (1) 245 --> EnglishMealIterator::current (1) 246 --> EnglishMealIterator::key (1) 247 248Top level 2: 249meal 1 => dinner 250 --> EuropeanMeals::getIterator 251 --> EnglishMealIterator::rewind (1) 252 --> EnglishMealIterator::valid (0) 253 --> EnglishMealIterator::current (0) 254 --> EnglishMealIterator::key (0) 255 meal 0 => breakfast 256 --> EnglishMealIterator::next (0) 257 --> EnglishMealIterator::valid (1) 258 --> EnglishMealIterator::current (1) 259 --> EnglishMealIterator::key (1) 260 meal 1 => dinner 261 --> EnglishMealIterator::next (1) 262 --> EnglishMealIterator::valid (2) 263 --> EnglishMealIterator::current (2) 264 --> EnglishMealIterator::key (2) 265 meal 2 => tea 266 --> EnglishMealIterator::next (2) 267 --> EnglishMealIterator::valid (3) 268 --> EnglishMealIterator::next (3) 269 --> EnglishMealIterator::valid (4) 270===DONE=== 271