PHP Iterators Part 3: SPL Filter Iterator, Append Iterator, and Multiple Iterator

We will talking in this part of the series (PHP Iterators) about there other important iterators which are Filter Iterator, Append Iterator, and Multiple Iterator.

 

 

Series Topics:

 

Filter Iterator

This iterator acts like the php function array_filter() which filters array values according to custom callback, but this iterator acts as Object Oriented Manner.

The filter iterator is an abstract iterator that filters out unwanted values. To use it you must extend it to implement custom iterator filters.

The most important method in this iterator is FilterIterator::accept() and it must be implemented in the subclasses.

 

Let’s see an example in action, suppose given the below array:

And we want to filter the the array items and get only the sold items, may be someone can do something like this:

Now using the Filter Iterator we can do this:

As shown in the code above we extend the FilterIterator class and implemented accept() method. This method must return a boolean value. If this value is false then the item is removed from the array otherwise it’s remain.

 

The FilterIterator constructor accept an iterator object not array so we injected the ArrayIterator of $products like this:

 

Let’s see another example:

In the example here we filtered the array based on a given value then we used the ArrayObject to retrieve the inner iterator using Arraybject::getIterator().

 

Append Iterator

The append iterator like the array_push() in arrays but for iterators used to iterate over several iterators one after the other so it looks like a long queue or string.

The append iterator incorporates a method AppendIterator::append() which takes an iterator object as an argument and pushes it into the iterator queue most like a multi dimensional array.

 

Let’s look at this example:

As shown here you need to use append() for each iterator you want to append. Additionally it’s possible to obtain the inner iterator that is currently iterated over with getInnerIterator() similar to other standard iterators. Also it’s possible to get all iterators via getArrayIterator()

 

Another example

Note here how the key is reset with each iterator start as if it be a separate loop.

 

Multiple Iterator

The multiple iterator is more like the append iterator except that instead of iterating over the iterators sequentially, the multiple iterator iterates over them in parallel. This behavior is useful when you need to traverse a group of collections in parallel order.

iterators the multiple iterator are attached instead of appended:

 

As it iterates over multiple iterators at once, things aren’t that straight forward. For example, the index or key of an element: Which one is it? By default, MultipleIterator will return an Array for both the current keys and values. As PHP does only allows an integer value or string as a “key”, the following example spits a warning:

Because by default MultipleIterator returns an invalid key (array), the warning appears and it is converted to 0. To obtain keys as well, the key() method needs to be called:

As you see above both $key and $value are an Array using implode here visualized what happens behind the scene.

 

The multiple iterator has two key constants:

  • MultipleIterator::MIT_KEYS_NUMERIC is the default one, it will return a numeric index (position), as usual 0-based -OR-
  • MultipleIterator::MIT_KEYS_ASSOC which will take the key value from the subiterator.

 

To make use of MultipleIterator::MIT_KEYS_ASSOC, the iterators needs to be attached with an integer or string value for the info parameter of attachIterator() (the second parameter). If set to MIT_KEYS_ASSOC that associated information will be taken. Example:

As for the first iterator 'foo' and for the second 'bar' is used for the info parameter and the assoc-flag is set, the output now contains those as keys:

 

If you don’t set the info parameter for one or more of the attached iterators and you make use of MIT_KEYS_ASSOC you’ll get an exception as the data is missing (NULL):

Fatal error: Uncaught exception ‘InvalidArgumentException’ with message ‘Sub-Iterator is associated with NULL’

Next to this key related behaviour, a question is what happens if one of the iterators is larger than the other? like A, B instead of A, B, C for the first iterator? By default the MultipleIterator will only return if all iterators are valid. The following output shows this, the last [2] => F element of the second iterator is just gone:

 

This behaviour can be changed with another pair of flags, one of the two MultipleIterator::MIT_NEED... ones:

  • MultipleIterator::MIT_NEED_ALL is the default one, it will invalidate the iteration if not all iterators are valid any longer -OR-
  • MultipleIterator::MIT_NEED_ANY will as long as at least one iterator is (still) valid.

output

The “missing” values in the output are actually NULL. As array keys can not be NULL, it’s safe to check with those if a sub-iterator did provide a value or not.

There is another pair of flags, that one controls what will be taken as keys.

All flags are listed in the PHP Manual as well. They can be changed while iterating with the setFlags() and getFlags() returns the current flags.

 

 

 

Conclusion

In this tutorial of this series (PHP Iterators) we talked about three other SPL Iterators, Starting from the filter iterator to filter collections and the append and multiple iterators to iterator over several iterators at once.

Share this: