class MyClass
{
public $var1 = 'value 1';
public $var2 = 'value 2';
public $var3 = 'value 3';
protected $protected = 'protected var';
private $private = 'private var';
function iterateVisible() {
echo "MyClass::iterateVisible:\n";
foreach($this as $key => $value) {
print "$key => $value\n";
}
}
}
$class = new MyClass();
foreach($class as $key => $value) {
print "$key => $value\n";
}
echo "\n";
$class->iterateVisible();
Результат выполнения данного примера:
var1 => value 1
var2 => value 2
var3 => value 3
MyClass::iterateVisible:
var1 => value 1
var2 => value 2
var3 => value 3
protected => protected var
private => private varКак показывает результат, foreach проитерировал все доступные и принадлежащие объекту видимые свойства.
Кроме того, вы можете развить эту концепцию и реализовать встроенный в PHP 5 интерфейс Iterator. Это позволит самому объекту решать как он будет итерироваться и какие данные будут доступны на каждой итерации.
Пример #2 Объект Iteration, реализующий интерфейс Iterator
class MyIterator implements Iterator
{
private $var = array();
public function __construct($array)
{
if (is_array($array)) {
$this->var = $array;
}
}
public function rewind()
{
echo "перемотка в начало\n";
reset($this->var);
}
public function current()
{
$var = current($this->var);
echo "текущий: $var\n";
return $var;
}
public function key()
{
$var = key($this->var);
echo "ключ: $var\n";
return $var;
}
public function next()
{
$var = next($this->var);
echo "следующий: $var\n";
return $var;
}
public function valid()
{
$key = key($this->var);
$var = ($key !== NULL && $key !== FALSE);
echo "верный: $var\n";
return $var;
}
}
$values = array(1,2,3);
$it = new MyIterator($values);
foreach ($it as $a => $b) {
print "$a: $b\n";
}
Результат выполнения данного примера:
перемотка в начало
верный: 1
текущий: 1
ключ: 0
0: 1
следующий: 2
верный: 1
текущий: 2
ключ: 1
1: 2
следующий: 3
верный: 1
текущий: 3
ключ: 2
2: 3
следующий:
верный:Интерфейс IteratorAggregate может быть использован как альтернатива реализации всех методов интерфейса Iterator. IteratorAggregate требует чтобы был реализован только один метода - IteratorAggregate::getIterator(), который должен возвращать экземпляр класса, реализующий интерфейс Iterator.
Пример #3 Объект Iteration, реализующий интерфейс IteratorAggregate
class MyCollection implements IteratorAggregate
{
private $items = array();
private $count = 0;
// Требование интерфейса IteratorAggregate
public function getIterator() {
return new MyIterator($this->items);
}
public function add($value) {
$this->items[$this->count++] = $value;
}
}
$coll = new MyCollection();
$coll->add('value 1');
$coll->add('value 2');
$coll->add('value 3');
foreach ($coll as $key => $val) {
echo "ключ/значение: [$key -> $val]\n\n";
}
Результат выполнения данного примера:
перемотка в начало
текущий: value 1
верный: 1
текущий: value 1
ключ: 0
ключ/значение: [0 -> value 1]
следующий: value 2
текущий: value 2
верный: 1
текущий: value 2
ключ: 1
ключ/значение: [1 -> value 2]
следующий: value 3
текущий: value 3
верный: 1
текущий: value 3
ключ: 2
ключ/значение: [2 -> value 3]
следующий:
текущий:
верный:Замечание:
Больше примеров итераторов можно найти в расширении SPL.
Замечание:
Пользователи PHP 5.5 и более поздних версий также могут изучить генераторы, представляющие собой альтернативный способ определения итераторов.
User Contributed Notes 16 notes
4
php dot net dot nsp at cvogt dot org ¶1 year ago
public function valid()
{
return ! is_null(key($this->var));
}
0
jille at hexon dot cx ¶1 year ago
// Wont work!
foreach($collection as $a) {
foreach($collection as $b) {
var_dump($a->someFunc($b));
}
}
0
hlegius at gmail dot com ¶5 years ago
class ArrayAccessImpl implements ArrayAccess {
private $data = array();
public function offsetUnset($index) {}
public function offsetSet($index, $value) {
// echo ("SET: ".$index."<br />");
if(isset($data[$index])) {
unset($data[$index]);
}
$u = &$this->data[$index];
if(is_array($value)) {
$u = new ArrayAccessImpl();
foreach($value as $idx=>$e)
$u[$idx]=$e;
} else
$u=$value;
}
public function offsetGet($index) {
// echo ("GET: ".$index."<br />");
if(!isset($this->data[$index]))
$this->data[$index]=new ArrayAccessImpl();
return $this->data[$index];
}
public function offsetExists($index) {
// echo ("EXISTS: ".$index."<br />");
if(isset($this->data[$index])) {
if($this->data[$index] instanceof ArrayAccessImpl) {
if(count($this->data[$index]->data)>0)
return true;
else
return false;
} else
return true;
} else
return false;
}
}
echo "ArrayAccess implementation that behaves like a multi-level array<hr />";
$data = new ArrayAccessImpl();
$data['string']="Just a simple string";
$data['number']=33;
$data['array']['another_string']="Alpha";
$data['array']['some_object']=new stdClass();
$data['array']['another_array']['x']['y']="LOL @ Whoever said it can't be done !";
$data['blank_array']=array();
echo "'array' Isset? "; print_r(isset($data['array'])); echo "<hr />";
echo "<pre>"; print_r($data['array']['non_existent']); echo "</pre>If attempting to read an offset that doesn't exist it returns a blank object! Use isset() to check if it exists!<br />";
echo "'non_existent' Isset? "; print_r(isset($data['array']['non_existent'])); echo "<br />";
echo "<pre>"; print_r($data['blank_array']); echo "</pre>A blank array unfortunately returns similar results :(<br />";
echo "'blank_array' Isset? "; print_r(isset($data['blank_array'])); echo "<hr />";
echo "<pre>"; print_r($data); echo "</pre> (non_existent remains in the structure. If someone can help to solve this I'll appreciate it)<hr />";
echo "Display some value that exists: ".$data['array']['another_string'];
0
doctorrock83_at_gmail.com ¶6 years ago
interface Iterator<O> {
boolean hasNext();
O next();
void remove();
}
0
chad 0x40 herballure 0x2e com ¶7 years ago
$A = array(TRUE, FALSE, TRUE, TRUE);
while(current($A) !== FALSE) {
var_dump(current($A));
next($A);
}
0
markushe at web dot de ¶8 years ago
class Collection implements ArrayAccess,IteratorAggregate
{
public $objectArray = Array();
//**these are the required iterator functions
function offsetExists($offset)
{
if(isset($this->objectArray[$offset])) return TRUE;
else return FALSE;
}
function & offsetGet($offset)
{
if ($this->offsetExists($offset)) return $this->objectArray[$offset];
else return (false);
}
function offsetSet($offset, $value)
{
if ($offset) $this->objectArray[$offset] = $value;
else $this->objectArray[] = $value;
}
function offsetUnset($offset)
{
unset ($this->objectArray[$offset]);
}
function & getIterator()
{
return new ArrayIterator($this->objectArray);
}
//**end required iterator functions
public function doSomething()
{
echo "I'm doing something";
}
}
0
PrzemekG_ at poczta dot onet dot pl ¶8 years ago
foreach($MyObject as $key => &$value)
$value = 'new '.$value;
0
strrev('ed.relpmeur@ekneos'); ¶8 years ago
Use the SPL ArrayAccess interface to call an object as array:
http://www.php.net/~helly/php/ext/spl/interfaceArrayAccess.html
0
phpnet at nicecupofteaandasitdown dot com ¶8 years ago
You should be prepared for your iterator's current method to be called before its next method is ever called. This certainly happens in a foreach loop. If your means of finding the next item is expensive you might want to use something like this
private $item;
function next() {
$this->item = &$this->getNextItem();
return $this->item;
}
public function current() {
if(!isset($this->item)) $this->next();
return $this->item;
}
0
knj at aider dot dk ¶8 years ago
if you in a string define classes that implements IteratorAggregate.
you cant use the default;
<?
...
public function getIterator() {
return new MyIterator(\\$this-><What ever>);
}
..
?>
at least not if you want to use eval(<The string>).
You have to use:
<?
...
public function getIterator() {
\\$arrayObj=new ArrayObject(\\$this-><What ever>);
return \\$arrayObj->getIterator();
}
...
?>
Смотрите также:
Описание на ru2.php.net
Описание на php.ru