Iterator tasarım deseni, bir nesneyi yinelenebilir hale getirmek için kullanılır ve iç ayrıntılarını göstermeden bir array gibi gösterir. Örneğin, karmaşık bir veri yapısı yinelenebilir bir nesneye dönüştürülür - mesela bir CSV dosyası. Aşağıdaki örnekte, bir CSV dosyasının satırlarını tek tek okumayı simüle edeceğiz, ancak OOP şeklinde.


Classlar


Line


class Line
{
private $id;
private $name;
private $surname;

public function __construct(int $id, string $name, string $surname)
{
$this->id = $id;
$this->name = $name;
$this->surname = $surname;
}

public function getId(): int
{
return $this->id;
}

public function getName(): string
{
return $this->name;
}

public function getSurname(): string
{
return $this->surname;
}

public function __toString(): string
{
return sprintf('%d, %s, %s', $this->id, $this->name, $this->surname);
}
}

LineCollection


class LineCollection implements \Countable, \IteratorAggregate
{
private $lines;

public function getLines(): ?array
{
return $this->lines;
}

public function addLine(Line $line): self
{
$this->lines[] = $line;

return $this;
}

public function removeLine(Line $line)
{
foreach ($this->lines as $key => $value) {
if ($value === $line) {
unset($this->lines[$key]);

break;
}
}
}

public function count(): int
{
return count($this->lines);
}

public function getIterator(): LineIterator
{
return new LineIterator($this);
}

public function getReverseIterator(): LineIterator
{
return new LineIterator($this, true);
}
}

LineIterator


class LineIterator implements \Iterator
{
private $lineCollection;
private $position;
private $reverse;

public function __construct(LineCollection $lineCollection, bool $reverse = false)
{
$this->lineCollection = $lineCollection;
$this->reverse = $reverse;
}

public function current(): ?Line
{
return $this->lineCollection->getLines()
? $this->lineCollection->getLines()[$this->position]
: null;
}

public function next(): void
{
$this->position = $this->position + ($this->reverse ? -1 : 1);
}

public function key(): int
{
return is_null($this->position) ? 0 : $this->position;
}

public function valid(): bool
{
return $this->lineCollection->getLines() && isset($this->lineCollection->getLines()[$this->position]);
}

public function rewind(): void
{
$this->position = $this->reverse ? $this->lineCollection->count() - 1 : 0;
}
}

Kullanım


// Assume that this is a CSV file
$csvFile[0]['id'] = 1;
$csvFile[0]['name'] = 'John';
$csvFile[0]['surname'] = 'Travolta';
$csvFile[1]['id'] = 2;
$csvFile[1]['name'] = 'Robert';
$csvFile[1]['surname'] = 'De Niro';
//

// Populate collection
$lineCollection = new LineCollection();
foreach ($csvFile as $row) {
$line = new Line($row['id'], $row['name'], $row['surname']);

$lineCollection->addLine($line);
}
//

print_r($lineCollection);
echo PHP_EOL;

// Iterate in normal order
foreach ($lineCollection->getIterator() as $line) {
echo $line->__toString().PHP_EOL;
}
//

echo PHP_EOL;

// Iterate in reverse order
foreach ($lineCollection->getReverseIterator() as $line) {
echo $line->__toString().PHP_EOL;

$lineCollection->removeLine($line); // Clear for demonstration purposes
}
//

echo PHP_EOL;
print_r($lineCollection);

Sonuç


LineCollection Object
(
[lines:LineCollection:private] => Array
(
[0] => Line Object
(
[id:Line:private] => 1
[name:Line:private] => John
[surname:Line:private] => Travolta
)

[1] => Line Object
(
[id:Line:private] => 2
[name:Line:private] => Robert
[surname:Line:private] => De Niro
)
)
)

1, John, Travolta
2, Robert, De Niro

2, Robert, De Niro
1, John, Travolta

LineCollection Object
(
[lines:LineCollection:private] => Array
(
)
)