Advanced Iteration

Back

Loading concept...

PHP Advanced Iteration: The Magic Conveyor Belt 🏭

Imagine a factory with a super-smart conveyor belt. Instead of loading ALL items at once (heavy!), it gives you ONE item at a time. That’s what PHP’s advanced iteration tools do—smart, memory-friendly, powerful!


🎯 The Big Picture

Think of a toy factory:

  • Old way: Dump ALL toys in one giant box, then sort through → Heavy, slow, messy!
  • New way: A conveyor belt hands you ONE toy at a time → Light, fast, clean!

PHP gives you tools to build these smart conveyor belts. Let’s explore each one!


1. Generators: The Lazy Factory Worker

What is it?

A Generator is like a worker who only makes ONE item when you ask for it. No wasted effort!

Simple Example

function countToThree() {
    yield 1;
    yield 2;
    yield 3;
}

foreach (countToThree() as $num) {
    echo $num; // Prints: 1, 2, 3
}

Why is this cool?

  • Regular function: Makes ALL items, stores them in memory
  • Generator: Makes ONE item, forgets it, makes the next

Real Life Example

// Reading a HUGE file?
// Don't load it all at once!

function readBigFile($file) {
    $handle = fopen($file, 'r');
    while ($line = fgets($handle)) {
        yield $line;
    }
    fclose($handle);
}

// Uses almost NO memory!
foreach (readBigFile('huge.txt') as $line) {
    echo $line;
}

2. The yield Keyword: The Pause Button

What is it?

yield is like pressing PAUSE on your work. You give out ONE result, then WAIT until someone asks for more.

Think of it like…

You’re reading a story to kids. After each page, you pause and wait for them to say “MORE!”

function storyPages() {
    yield "Once upon a time...";
    yield "The hero found a dragon!";
    yield "They became friends.";
    yield "The End.";
}

Key Difference from return

return yield
Stops everything Pauses, waits
Gives ONE result Gives MANY results
Function ends Function continues

Sending Values Back

function printer() {
    while (true) {
        $value = yield;
        echo "Got: $value\n";
    }
}

$gen = printer();
$gen->send("Hello");  // Got: Hello
$gen->send("World");  // Got: World

3. Iterator Interface: The Rule Book

What is it?

The Iterator Interface is like a rule book that says: “If you want to be loopable, you MUST have these 5 abilities!”

The 5 Magic Abilities

graph TD A["Iterator Interface"] --> B["rewind: Go to start"] A --> C["current: Get current item"] A --> D["key: Get current position"] A --> E["next: Move forward"] A --> F["valid: More items left?"]

Building Your Own Iterator

class NumberRange implements Iterator {
    private $start;
    private $end;
    private $current;

    public function __construct($start, $end) {
        $this->start = $start;
        $this->end = $end;
    }

    public function rewind(): void {
        $this->current = $this->start;
    }

    public function current(): mixed {
        return $this->current;
    }

    public function key(): mixed {
        return $this->current - $this->start;
    }

    public function next(): void {
        $this->current++;
    }

    public function valid(): bool {
        return $this->current <= $this->end;
    }
}

// Now use it!
foreach (new NumberRange(5, 10) as $num) {
    echo $num; // 5, 6, 7, 8, 9, 10
}

4. IteratorAggregate: The Shortcut

What is it?

Too lazy to write 5 methods? IteratorAggregate says: “Just give me ONE method that returns an iterator, and I’ll handle the rest!”

The Simple Rule

Just implement getIterator() → Done!

class BookShelf implements IteratorAggregate {
    private $books = [];

    public function addBook($book) {
        $this->books[] = $book;
    }

    // Just ONE method needed!
    public function getIterator(): Traversable {
        return new ArrayIterator($this->books);
    }
}

$shelf = new BookShelf();
$shelf->addBook("Harry Potter");
$shelf->addBook("Lord of the Rings");

foreach ($shelf as $book) {
    echo $book; // Works perfectly!
}

Iterator vs IteratorAggregate

Iterator IteratorAggregate
5 methods to write 1 method to write
Full control Quick & easy
Custom logic Delegates to another iterator

5. ArrayIterator: The Ready-Made Helper

What is it?

ArrayIterator is like a pre-built conveyor belt. Give it an array, and it becomes loopable with extra powers!

Basic Usage

$fruits = ['apple', 'banana', 'cherry'];
$iterator = new ArrayIterator($fruits);

// Loop normally
foreach ($iterator as $fruit) {
    echo $fruit;
}

// Or use methods
$iterator->rewind();
echo $iterator->current(); // apple
$iterator->next();
echo $iterator->current(); // banana

Extra Powers

$iterator = new ArrayIterator([3, 1, 2]);

// Sort it!
$iterator->asort();

// Count it!
echo $iterator->count(); // 3

// Seek to position!
$iterator->seek(1);
echo $iterator->current();

6. Countable Interface: The Counter

What is it?

Want your object to work with count()? Implement Countable!

The ONE Rule

Just implement count() method.

class Playlist implements Countable {
    private $songs = [];

    public function addSong($song) {
        $this->songs[] = $song;
    }

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

$playlist = new Playlist();
$playlist->addSong("Song A");
$playlist->addSong("Song B");

echo count($playlist); // 2 - Works!

Combining with IteratorAggregate

class TodoList implements
    IteratorAggregate,
    Countable
{
    private $tasks = [];

    public function add($task) {
        $this->tasks[] = $task;
    }

    public function getIterator(): Traversable {
        return new ArrayIterator($this->tasks);
    }

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

$todos = new TodoList();
$todos->add("Buy milk");
$todos->add("Walk dog");

echo count($todos); // 2
foreach ($todos as $task) {
    echo $task;
}

7. ArrayAccess Interface: Act Like an Array!

What is it?

Want to use $object['key'] like an array? ArrayAccess gives your object array superpowers!

The 4 Methods

graph TD A["ArrayAccess"] --> B["offsetExists: Does key exist?"] A --> C["offsetGet: Get value by key"] A --> D["offsetSet: Set value by key"] A --> E["offsetUnset: Remove by key"]

Full Example

class Settings implements ArrayAccess {
    private $data = [];

    public function offsetExists($key): bool {
        return isset($this->data[$key]);
    }

    public function offsetGet($key): mixed {
        return $this->data[$key] ?? null;
    }

    public function offsetSet($key, $val): void {
        $this->data[$key] = $val;
    }

    public function offsetUnset($key): void {
        unset($this->data[$key]);
    }
}

$settings = new Settings();
$settings['theme'] = 'dark';    // offsetSet
echo $settings['theme'];         // offsetGet → dark
isset($settings['theme']);       // offsetExists → true
unset($settings['theme']);       // offsetUnset

🏆 The Ultimate Combo: All Powers Combined!

class SuperCollection implements
    IteratorAggregate,
    Countable,
    ArrayAccess
{
    private $items = [];

    // ArrayAccess methods
    public function offsetExists($k): bool {
        return isset($this->items[$k]);
    }
    public function offsetGet($k): mixed {
        return $this->items[$k];
    }
    public function offsetSet($k, $v): void {
        $this->items[$k] = $v;
    }
    public function offsetUnset($k): void {
        unset($this->items[$k]);
    }

    // Countable
    public function count(): int {
        return count($this->items);
    }

    // IteratorAggregate
    public function getIterator(): Traversable {
        return new ArrayIterator($this->items);
    }
}

$c = new SuperCollection();
$c['a'] = 1;          // Array syntax!
$c['b'] = 2;
echo count($c);       // 2
foreach ($c as $v) {  // Loopable!
    echo $v;
}

🎯 Quick Summary

Tool Purpose Key Point
Generator Lazy data production Saves memory
yield Pause & return one value Like a pause button
Iterator Make anything loopable 5 methods required
IteratorAggregate Quick loopable shortcut 1 method only
ArrayIterator Ready-made iterator Works with arrays
Countable Enable count() 1 method: count()
ArrayAccess Array syntax for objects 4 methods for []

🚀 When to Use What?

graph TD Q["Need to iterate?"] --> A{Memory concern?} A -->|Yes| G["Use Generator"] A -->|No| B{Custom logic?} B -->|Complex| I["Use Iterator"] B -->|Simple| IA["Use IteratorAggregate"] Q2["Need count?"] --> C["Implement Countable"] Q3["Need array syntax?"] --> AA["Implement ArrayAccess"]

Remember: These tools are like LEGO blocks. Mix and match to build exactly what you need!

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.