How to build your own PHP collection using the iterator

Alin Pintilie
2 min readFeb 6, 2023

--

If you are a PHP programmer you understand what array means for us. We gravitate around it. Indubitably there are a lot of advantages but also there are some drawbacks. For example, in java, if you want to work with a collection, you can define what kind of data you want to store and you should not worry later if that collection could contain other data too. From this perspective, we can not do this in PHP, so in order to achieve this we may use a collection. A collection could be just a wrapper over an array. If you are familiar with Laravel or another PHP framework maybe you know what I mean.

For the purpose of showing how to build a collection, I propose the following scenario. We are working with Invoices objects and we want to have a collection that contains only objects of Invoice type. Of course, we can use an array and add validation every time when we add and retrieve items but this could be inefficient and error-prone. So we are building our own collection that will be framework agnostic.

In order to do this we use IteratorAggregate. More about it can be read here.

class InvoiceCollection implements IteratorAggregate {
private $invoices = array();

public function add(Invoice $invoice)
{
$this->invoices[] = $invoice;
}

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

Using the IteratorAggregate we must implement the getIterator function. All that is done is to return a Traversable. Basically “we convert” $invoices array into an Iterator with ArrayIterator function. Also, we implement add function that will be the unique entry point of items into the array. Because we declared the parameter type as Invoice this function will accept an only objects of that type.

Using this collection is very easy:

//adding an item 
$invoiceCollection = new InvoiceCollection();
$invoiceCollection->add(new Invoice(1));

//iterating over it
foreach ($invoiceCollection as $invoice) {
//do something with invoice
}

Now we should not implement any other logic when adding or iterating over this collection as it contains only Invoice objects. Of course, we can add more functionality like get, delete, count, etc. functions to our class. Depending on your own needs feel free to use the power of this mechanism.

Thank you

--

--