6 changed files with 720 additions and 0 deletions
-
135tests/lang/foreachLoopIterator.001.phpt
-
24tests/lang/foreachLoopIterator.002.phpt
-
270tests/lang/foreachLoopIteratorAggregate.001.phpt
-
53tests/lang/foreachLoopIteratorAggregate.002.phpt
-
134tests/lang/foreachLoopIteratorAggregate.003.phpt
-
104tests/lang/foreachLoopIteratorAggregate.004.phpt
@ -0,0 +1,135 @@ |
|||||
|
--TEST-- |
||||
|
foreach with Iterator. |
||||
|
--FILE-- |
||||
|
<?php |
||||
|
|
||||
|
class MealIterator implements Iterator { |
||||
|
private $pos=0; |
||||
|
private $myContent=array("breakfast", "lunch", "dinner"); |
||||
|
|
||||
|
public function valid() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return $this->pos<3; |
||||
|
} |
||||
|
|
||||
|
public function next() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return $this->myContent[$this->pos++]; |
||||
|
} |
||||
|
|
||||
|
public function rewind() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
$this->pos=0; |
||||
|
} |
||||
|
|
||||
|
public function current() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return $this->myContent[$this->pos]; |
||||
|
} |
||||
|
|
||||
|
public function key() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return "meal " . $this->pos; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
$f = new MealIterator; |
||||
|
var_dump($f); |
||||
|
|
||||
|
echo "-----( Simple iteration: )-----\n"; |
||||
|
foreach ($f as $k=>$v) { |
||||
|
echo "$k => $v\n"; |
||||
|
} |
||||
|
|
||||
|
$f->rewind(); |
||||
|
|
||||
|
$indent = " "; |
||||
|
|
||||
|
echo "\n\n\n-----( Nested iteration: )-----\n"; |
||||
|
$count=1; |
||||
|
foreach ($f as $k=>$v) { |
||||
|
echo "\nTop level " . $count++ . ": \n"; |
||||
|
echo "$k => $v\n"; |
||||
|
$indent = " "; |
||||
|
foreach ($f as $k=>$v) { |
||||
|
echo " $k => $v\n"; |
||||
|
} |
||||
|
$indent = " "; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
?> |
||||
|
===DONE=== |
||||
|
--EXPECTF-- |
||||
|
object(MealIterator)#%d (2) { |
||||
|
["pos:private"]=> |
||||
|
int(0) |
||||
|
["myContent:private"]=> |
||||
|
array(3) { |
||||
|
[0]=> |
||||
|
string(9) "breakfast" |
||||
|
[1]=> |
||||
|
string(5) "lunch" |
||||
|
[2]=> |
||||
|
string(6) "dinner" |
||||
|
} |
||||
|
} |
||||
|
-----( Simple iteration: )----- |
||||
|
--> MealIterator::rewind (0) |
||||
|
--> MealIterator::valid (0) |
||||
|
--> MealIterator::current (0) |
||||
|
--> MealIterator::key (0) |
||||
|
meal 0 => breakfast |
||||
|
--> MealIterator::next (0) |
||||
|
--> MealIterator::valid (1) |
||||
|
--> MealIterator::current (1) |
||||
|
--> MealIterator::key (1) |
||||
|
meal 1 => lunch |
||||
|
--> MealIterator::next (1) |
||||
|
--> MealIterator::valid (2) |
||||
|
--> MealIterator::current (2) |
||||
|
--> MealIterator::key (2) |
||||
|
meal 2 => dinner |
||||
|
--> MealIterator::next (2) |
||||
|
--> MealIterator::valid (3) |
||||
|
--> MealIterator::rewind (3) |
||||
|
|
||||
|
|
||||
|
|
||||
|
-----( Nested iteration: )----- |
||||
|
--> MealIterator::rewind (0) |
||||
|
--> MealIterator::valid (0) |
||||
|
--> MealIterator::current (0) |
||||
|
--> MealIterator::key (0) |
||||
|
|
||||
|
Top level 1: |
||||
|
meal 0 => breakfast |
||||
|
--> MealIterator::rewind (0) |
||||
|
--> MealIterator::valid (0) |
||||
|
--> MealIterator::current (0) |
||||
|
--> MealIterator::key (0) |
||||
|
meal 0 => breakfast |
||||
|
--> MealIterator::next (0) |
||||
|
--> MealIterator::valid (1) |
||||
|
--> MealIterator::current (1) |
||||
|
--> MealIterator::key (1) |
||||
|
meal 1 => lunch |
||||
|
--> MealIterator::next (1) |
||||
|
--> MealIterator::valid (2) |
||||
|
--> MealIterator::current (2) |
||||
|
--> MealIterator::key (2) |
||||
|
meal 2 => dinner |
||||
|
--> MealIterator::next (2) |
||||
|
--> MealIterator::valid (3) |
||||
|
--> MealIterator::next (3) |
||||
|
|
||||
|
Notice: Undefined offset: 3 in %s on line %d |
||||
|
--> MealIterator::valid (4) |
||||
|
===DONE=== |
||||
@ -0,0 +1,24 @@ |
|||||
|
--TEST-- |
||||
|
foreach with iterator and &$value reference |
||||
|
--FILE-- |
||||
|
<?php |
||||
|
|
||||
|
class MyIterator implements Iterator { |
||||
|
public function valid() { return true; } |
||||
|
public function next() { } |
||||
|
public function rewind() { } |
||||
|
public function current() { } |
||||
|
public function key() { } |
||||
|
} |
||||
|
|
||||
|
$f = new MyIterator; |
||||
|
echo "-----( Try to iterate with &\$value: )-----\n"; |
||||
|
foreach ($f as $k=>&$v) { |
||||
|
echo "$k => $v\n"; |
||||
|
} |
||||
|
|
||||
|
?> |
||||
|
--EXPECTF-- |
||||
|
-----( Try to iterate with &$value: )----- |
||||
|
|
||||
|
Fatal error: An iterator cannot be used with foreach by reference in %s on line 13 |
||||
@ -0,0 +1,270 @@ |
|||||
|
--TEST-- |
||||
|
foreach with iteratorAggregate |
||||
|
--FILE-- |
||||
|
<?php |
||||
|
class EnglishMealIterator implements Iterator { |
||||
|
private $pos=0; |
||||
|
private $myContent=array("breakfast", "dinner", "tea"); |
||||
|
|
||||
|
public function valid() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return $this->pos < count($this->myContent); |
||||
|
} |
||||
|
|
||||
|
public function next() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
$this->pos++; |
||||
|
} |
||||
|
|
||||
|
public function rewind() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
$this->pos=0; |
||||
|
} |
||||
|
|
||||
|
public function current() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return $this->myContent[$this->pos]; |
||||
|
} |
||||
|
|
||||
|
public function key() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return "meal " . $this->pos; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
class FrenchMealIterator implements Iterator { |
||||
|
private $pos=0; |
||||
|
private $myContent=array("petit dejeuner", "dejeuner", "gouter", "dinner"); |
||||
|
|
||||
|
public function valid() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return $this->pos < count($this->myContent); |
||||
|
} |
||||
|
|
||||
|
public function next() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
$this->pos++; |
||||
|
} |
||||
|
|
||||
|
public function rewind() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
$this->pos=0; |
||||
|
} |
||||
|
|
||||
|
public function current() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return $this->myContent[$this->pos]; |
||||
|
} |
||||
|
|
||||
|
public function key() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return "meal " . $this->pos; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
Class EuropeanMeals implements IteratorAggregate { |
||||
|
|
||||
|
private $storedEnglishMealIterator; |
||||
|
private $storedFrenchMealIterator; |
||||
|
|
||||
|
public function __construct() { |
||||
|
$this->storedEnglishMealIterator = new EnglishMealIterator; |
||||
|
$this->storedFrenchMealIterator = new FrenchMealIterator; |
||||
|
} |
||||
|
|
||||
|
public function getIterator() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . "\n"; |
||||
|
|
||||
|
//Alternate between English and French meals |
||||
|
static $i = 0; |
||||
|
if ($i++%2 == 0) { |
||||
|
return $this->storedEnglishMealIterator; |
||||
|
} else { |
||||
|
return $this->storedFrenchMealIterator; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
$f = new EuropeanMeals; |
||||
|
var_dump($f); |
||||
|
|
||||
|
echo "-----( Simple iteration 1: )-----\n"; |
||||
|
foreach ($f as $k=>$v) { |
||||
|
echo "$k => $v\n"; |
||||
|
} |
||||
|
echo "-----( Simple iteration 2: )-----\n"; |
||||
|
foreach ($f as $k=>$v) { |
||||
|
echo "$k => $v\n"; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
$indent = " "; |
||||
|
echo "\n\n\n-----( Nested iteration: )-----\n"; |
||||
|
$count=1; |
||||
|
foreach ($f as $k=>$v) { |
||||
|
echo "\nTop level " . $count++ . ": \n"; |
||||
|
echo "$k => $v\n"; |
||||
|
$indent = " "; |
||||
|
foreach ($f as $k=>$v) { |
||||
|
echo " $k => $v\n"; |
||||
|
} |
||||
|
$indent = " "; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
?> |
||||
|
===DONE=== |
||||
|
--EXPECTF-- |
||||
|
object(EuropeanMeals)#%d (2) { |
||||
|
["storedEnglishMealIterator:private"]=> |
||||
|
object(EnglishMealIterator)#%d (2) { |
||||
|
["pos:private"]=> |
||||
|
int(0) |
||||
|
["myContent:private"]=> |
||||
|
array(3) { |
||||
|
[0]=> |
||||
|
string(9) "breakfast" |
||||
|
[1]=> |
||||
|
string(6) "dinner" |
||||
|
[2]=> |
||||
|
string(3) "tea" |
||||
|
} |
||||
|
} |
||||
|
["storedFrenchMealIterator:private"]=> |
||||
|
object(FrenchMealIterator)#%d (2) { |
||||
|
["pos:private"]=> |
||||
|
int(0) |
||||
|
["myContent:private"]=> |
||||
|
array(4) { |
||||
|
[0]=> |
||||
|
string(%d) "petit dejeuner" |
||||
|
[1]=> |
||||
|
string(%d) "dejeuner" |
||||
|
[2]=> |
||||
|
string(%d) "gouter" |
||||
|
[3]=> |
||||
|
string(6) "dinner" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
-----( Simple iteration 1: )----- |
||||
|
--> EuropeanMeals::getIterator |
||||
|
--> EnglishMealIterator::rewind (0) |
||||
|
--> EnglishMealIterator::valid (0) |
||||
|
--> EnglishMealIterator::current (0) |
||||
|
--> EnglishMealIterator::key (0) |
||||
|
meal 0 => breakfast |
||||
|
--> EnglishMealIterator::next (0) |
||||
|
--> EnglishMealIterator::valid (1) |
||||
|
--> EnglishMealIterator::current (1) |
||||
|
--> EnglishMealIterator::key (1) |
||||
|
meal 1 => dinner |
||||
|
--> EnglishMealIterator::next (1) |
||||
|
--> EnglishMealIterator::valid (2) |
||||
|
--> EnglishMealIterator::current (2) |
||||
|
--> EnglishMealIterator::key (2) |
||||
|
meal 2 => tea |
||||
|
--> EnglishMealIterator::next (2) |
||||
|
--> EnglishMealIterator::valid (3) |
||||
|
-----( Simple iteration 2: )----- |
||||
|
--> EuropeanMeals::getIterator |
||||
|
--> FrenchMealIterator::rewind (0) |
||||
|
--> FrenchMealIterator::valid (0) |
||||
|
--> FrenchMealIterator::current (0) |
||||
|
--> FrenchMealIterator::key (0) |
||||
|
meal 0 => petit dejeuner |
||||
|
--> FrenchMealIterator::next (0) |
||||
|
--> FrenchMealIterator::valid (1) |
||||
|
--> FrenchMealIterator::current (1) |
||||
|
--> FrenchMealIterator::key (1) |
||||
|
meal 1 => dejeuner |
||||
|
--> FrenchMealIterator::next (1) |
||||
|
--> FrenchMealIterator::valid (2) |
||||
|
--> FrenchMealIterator::current (2) |
||||
|
--> FrenchMealIterator::key (2) |
||||
|
meal 2 => gouter |
||||
|
--> FrenchMealIterator::next (2) |
||||
|
--> FrenchMealIterator::valid (3) |
||||
|
--> FrenchMealIterator::current (3) |
||||
|
--> FrenchMealIterator::key (3) |
||||
|
meal 3 => dinner |
||||
|
--> FrenchMealIterator::next (3) |
||||
|
--> FrenchMealIterator::valid (4) |
||||
|
|
||||
|
|
||||
|
|
||||
|
-----( Nested iteration: )----- |
||||
|
--> EuropeanMeals::getIterator |
||||
|
--> EnglishMealIterator::rewind (3) |
||||
|
--> EnglishMealIterator::valid (0) |
||||
|
--> EnglishMealIterator::current (0) |
||||
|
--> EnglishMealIterator::key (0) |
||||
|
|
||||
|
Top level 1: |
||||
|
meal 0 => breakfast |
||||
|
--> EuropeanMeals::getIterator |
||||
|
--> FrenchMealIterator::rewind (4) |
||||
|
--> FrenchMealIterator::valid (0) |
||||
|
--> FrenchMealIterator::current (0) |
||||
|
--> FrenchMealIterator::key (0) |
||||
|
meal 0 => petit dejeuner |
||||
|
--> FrenchMealIterator::next (0) |
||||
|
--> FrenchMealIterator::valid (1) |
||||
|
--> FrenchMealIterator::current (1) |
||||
|
--> FrenchMealIterator::key (1) |
||||
|
meal 1 => dejeuner |
||||
|
--> FrenchMealIterator::next (1) |
||||
|
--> FrenchMealIterator::valid (2) |
||||
|
--> FrenchMealIterator::current (2) |
||||
|
--> FrenchMealIterator::key (2) |
||||
|
meal 2 => gouter |
||||
|
--> FrenchMealIterator::next (2) |
||||
|
--> FrenchMealIterator::valid (3) |
||||
|
--> FrenchMealIterator::current (3) |
||||
|
--> FrenchMealIterator::key (3) |
||||
|
meal 3 => dinner |
||||
|
--> FrenchMealIterator::next (3) |
||||
|
--> FrenchMealIterator::valid (4) |
||||
|
--> EnglishMealIterator::next (0) |
||||
|
--> EnglishMealIterator::valid (1) |
||||
|
--> EnglishMealIterator::current (1) |
||||
|
--> EnglishMealIterator::key (1) |
||||
|
|
||||
|
Top level 2: |
||||
|
meal 1 => dinner |
||||
|
--> EuropeanMeals::getIterator |
||||
|
--> EnglishMealIterator::rewind (1) |
||||
|
--> EnglishMealIterator::valid (0) |
||||
|
--> EnglishMealIterator::current (0) |
||||
|
--> EnglishMealIterator::key (0) |
||||
|
meal 0 => breakfast |
||||
|
--> EnglishMealIterator::next (0) |
||||
|
--> EnglishMealIterator::valid (1) |
||||
|
--> EnglishMealIterator::current (1) |
||||
|
--> EnglishMealIterator::key (1) |
||||
|
meal 1 => dinner |
||||
|
--> EnglishMealIterator::next (1) |
||||
|
--> EnglishMealIterator::valid (2) |
||||
|
--> EnglishMealIterator::current (2) |
||||
|
--> EnglishMealIterator::key (2) |
||||
|
meal 2 => tea |
||||
|
--> EnglishMealIterator::next (2) |
||||
|
--> EnglishMealIterator::valid (3) |
||||
|
--> EnglishMealIterator::next (3) |
||||
|
--> EnglishMealIterator::valid (4) |
||||
|
===DONE=== |
||||
@ -0,0 +1,53 @@ |
|||||
|
--TEST-- |
||||
|
IteratorAggregate::getIterator bad return type |
||||
|
--FILE-- |
||||
|
<?php |
||||
|
|
||||
|
class bad1 implements IteratorAggregate { |
||||
|
function getIterator() { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class bad2 implements IteratorAggregate { |
||||
|
function getIterator() { |
||||
|
return new stdClass; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class bad3 implements IteratorAggregate { |
||||
|
function getIterator() { |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class bad4 implements IteratorAggregate { |
||||
|
function getIterator() { |
||||
|
return array(1,2,3); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
function f($className) { |
||||
|
try { |
||||
|
foreach (new $className as $k=>$v) { |
||||
|
echo "$k => $v\n"; |
||||
|
} |
||||
|
} catch (Exception $e) { |
||||
|
echo $e->getLine() . ": " . $e->getMessage() ."\n"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
f("bad1"); |
||||
|
f("bad2"); |
||||
|
f("bad3"); |
||||
|
f("bad4"); |
||||
|
|
||||
|
?> |
||||
|
===DONE=== |
||||
|
--EXPECTF-- |
||||
|
30: Objects returned by bad1::getIterator() must be traversable or implement interface Iterator |
||||
|
30: Objects returned by bad2::getIterator() must be traversable or implement interface Iterator |
||||
|
30: Objects returned by bad3::getIterator() must be traversable or implement interface Iterator |
||||
|
30: Objects returned by bad4::getIterator() must be traversable or implement interface Iterator |
||||
|
===DONE=== |
||||
@ -0,0 +1,134 @@ |
|||||
|
--TEST-- |
||||
|
foreach with nested iteratorAggregates |
||||
|
--FILE-- |
||||
|
<?php |
||||
|
class EnglishMealIterator implements Iterator { |
||||
|
private $pos=0; |
||||
|
private $myContent=array("breakfast", "dinner", "tea"); |
||||
|
|
||||
|
public function valid() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return $this->pos<3; |
||||
|
} |
||||
|
|
||||
|
public function next() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return $this->myContent[$this->pos++]; |
||||
|
} |
||||
|
|
||||
|
public function rewind() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
$this->pos=0; |
||||
|
} |
||||
|
|
||||
|
public function current() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return $this->myContent[$this->pos]; |
||||
|
} |
||||
|
|
||||
|
public function key() { |
||||
|
global $indent; |
||||
|
echo "$indent--> " . __METHOD__ . " ($this->pos)\n"; |
||||
|
return "meal " . $this->pos; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
class A1 implements IteratorAggregate { |
||||
|
function getIterator() { |
||||
|
return new EnglishMealIterator; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class A2 implements IteratorAggregate { |
||||
|
function getIterator() { |
||||
|
return new A1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class A3 implements IteratorAggregate { |
||||
|
function getIterator() { |
||||
|
return new A2; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
echo "\n-----( A1: )-----\n"; |
||||
|
foreach (new A1 as $k=>$v) { |
||||
|
echo "$k => $v\n"; |
||||
|
} |
||||
|
|
||||
|
echo "\n-----( A2: )-----\n"; |
||||
|
foreach (new A2 as $k=>$v) { |
||||
|
echo "$k => $v\n"; |
||||
|
} |
||||
|
|
||||
|
echo "\n-----( A3: )-----\n"; |
||||
|
foreach (new A3 as $k=>$v) { |
||||
|
echo "$k => $v\n"; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
?> |
||||
|
===DONE=== |
||||
|
--EXPECTF-- |
||||
|
-----( A1: )----- |
||||
|
--> EnglishMealIterator::rewind (0) |
||||
|
--> EnglishMealIterator::valid (0) |
||||
|
--> EnglishMealIterator::current (0) |
||||
|
--> EnglishMealIterator::key (0) |
||||
|
meal 0 => breakfast |
||||
|
--> EnglishMealIterator::next (0) |
||||
|
--> EnglishMealIterator::valid (1) |
||||
|
--> EnglishMealIterator::current (1) |
||||
|
--> EnglishMealIterator::key (1) |
||||
|
meal 1 => dinner |
||||
|
--> EnglishMealIterator::next (1) |
||||
|
--> EnglishMealIterator::valid (2) |
||||
|
--> EnglishMealIterator::current (2) |
||||
|
--> EnglishMealIterator::key (2) |
||||
|
meal 2 => tea |
||||
|
--> EnglishMealIterator::next (2) |
||||
|
--> EnglishMealIterator::valid (3) |
||||
|
|
||||
|
-----( A2: )----- |
||||
|
--> EnglishMealIterator::rewind (0) |
||||
|
--> EnglishMealIterator::valid (0) |
||||
|
--> EnglishMealIterator::current (0) |
||||
|
--> EnglishMealIterator::key (0) |
||||
|
meal 0 => breakfast |
||||
|
--> EnglishMealIterator::next (0) |
||||
|
--> EnglishMealIterator::valid (1) |
||||
|
--> EnglishMealIterator::current (1) |
||||
|
--> EnglishMealIterator::key (1) |
||||
|
meal 1 => dinner |
||||
|
--> EnglishMealIterator::next (1) |
||||
|
--> EnglishMealIterator::valid (2) |
||||
|
--> EnglishMealIterator::current (2) |
||||
|
--> EnglishMealIterator::key (2) |
||||
|
meal 2 => tea |
||||
|
--> EnglishMealIterator::next (2) |
||||
|
--> EnglishMealIterator::valid (3) |
||||
|
|
||||
|
-----( A3: )----- |
||||
|
--> EnglishMealIterator::rewind (0) |
||||
|
--> EnglishMealIterator::valid (0) |
||||
|
--> EnglishMealIterator::current (0) |
||||
|
--> EnglishMealIterator::key (0) |
||||
|
meal 0 => breakfast |
||||
|
--> EnglishMealIterator::next (0) |
||||
|
--> EnglishMealIterator::valid (1) |
||||
|
--> EnglishMealIterator::current (1) |
||||
|
--> EnglishMealIterator::key (1) |
||||
|
meal 1 => dinner |
||||
|
--> EnglishMealIterator::next (1) |
||||
|
--> EnglishMealIterator::valid (2) |
||||
|
--> EnglishMealIterator::current (2) |
||||
|
--> EnglishMealIterator::key (2) |
||||
|
meal 2 => tea |
||||
|
--> EnglishMealIterator::next (2) |
||||
|
--> EnglishMealIterator::valid (3) |
||||
|
===DONE=== |
||||
@ -0,0 +1,104 @@ |
|||||
|
--TEST-- |
||||
|
Duplicate of zend test tests/classes/iterators_002.phpt without expected output from destructor |
||||
|
--FILE-- |
||||
|
<?php |
||||
|
class c_iter implements Iterator { |
||||
|
|
||||
|
private $obj; |
||||
|
private $num = 0; |
||||
|
|
||||
|
function __construct($obj) { |
||||
|
echo __METHOD__ . "\n"; |
||||
|
$this->obj = $obj; |
||||
|
} |
||||
|
function rewind() { |
||||
|
echo __METHOD__ . "\n"; |
||||
|
$this->num = 0; |
||||
|
} |
||||
|
function valid() { |
||||
|
$more = $this->num < $this->obj->max; |
||||
|
echo __METHOD__ . ' = ' .($more ? 'true' : 'false') . "\n"; |
||||
|
return $more; |
||||
|
} |
||||
|
function current() { |
||||
|
echo __METHOD__ . "\n"; |
||||
|
return $this->num; |
||||
|
} |
||||
|
function next() { |
||||
|
echo __METHOD__ . "\n"; |
||||
|
$this->num++; |
||||
|
} |
||||
|
function key() { |
||||
|
echo __METHOD__ . "\n"; |
||||
|
switch($this->num) { |
||||
|
case 0: return "1st"; |
||||
|
case 1: return "2nd"; |
||||
|
case 2: return "3rd"; |
||||
|
default: return "???"; |
||||
|
} |
||||
|
} |
||||
|
function __destruct() { |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class c implements IteratorAggregate { |
||||
|
|
||||
|
public $max = 3; |
||||
|
|
||||
|
function getIterator() { |
||||
|
echo __METHOD__ . "\n"; |
||||
|
return new c_iter($this); |
||||
|
} |
||||
|
function __destruct() { |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$t = new c(); |
||||
|
|
||||
|
foreach($t as $k => $v) { |
||||
|
foreach($t as $w) { |
||||
|
echo "double:$v:$w\n"; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
unset($t); |
||||
|
|
||||
|
?> |
||||
|
===DONE=== |
||||
|
--EXPECT-- |
||||
|
c::getIterator |
||||
|
c_iter::__construct |
||||
|
c_iter::rewind |
||||
|
c_iter::valid = true |
||||
|
c_iter::current |
||||
|
c_iter::key |
||||
|
c::getIterator |
||||
|
c_iter::__construct |
||||
|
c_iter::rewind |
||||
|
c_iter::valid = true |
||||
|
c_iter::current |
||||
|
double:0:0 |
||||
|
c_iter::next |
||||
|
c_iter::valid = true |
||||
|
c_iter::current |
||||
|
c_iter::key |
||||
|
c::getIterator |
||||
|
c_iter::__construct |
||||
|
c_iter::rewind |
||||
|
c_iter::valid = true |
||||
|
c_iter::current |
||||
|
double:1:0 |
||||
|
c_iter::next |
||||
|
c_iter::valid = true |
||||
|
c_iter::current |
||||
|
c_iter::key |
||||
|
c::getIterator |
||||
|
c_iter::__construct |
||||
|
c_iter::rewind |
||||
|
c_iter::valid = true |
||||
|
c_iter::current |
||||
|
double:2:0 |
||||
|
c_iter::next |
||||
|
c_iter::valid = false |
||||
|
===DONE=== |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue