DEV Community


Posted on • Originally published at on

PHP Iterators Part 4: SPL Infinite, Limit, Globe and NoRewind Iterators

Continuing our series (PHP Iterators) to demonstrate the SPL PHP Iterators, we will discuss the infinite iterator, the limit iterator, the globe iterator, and the noRewind iterator.

To review the previous parts click here part1, part2, part3

Infinite Iterator

The infinite iterator is a kinda like an infinite loop that allows to perform operations which requires some recursion or when we need to iterate over an iterator infinitely without stopping.

InfiniteIterator extends IteratorIterator implements OuterIterator { /\* Some methods \*/ public \_\_construct ( Iterator $iterator ) public void next ( void ) /\* Inherited methods \*/ public IteratorIterator::\_\_construct ( Traversable $iterator ) public mixed IteratorIterator::current ( void ) public Traversable IteratorIterator::getInnerIterator ( void ) public scalar IteratorIterator::key ( void ) public void IteratorIterator::rewind ( void ) }

Note that when using the the infinite iterator it must be a termination condition that terminate the loop otherwise the loop will continue executing infinitely and the browser will crash.

let’s see an example:

\<?php $programming\_languages = array('C++', 'PHP', 'C#', 'Java', 'Swift'); $iterator = new InfiniteIterator(new ArrayIterator($programming\_languages)); $counter = 0; echo "\<pre\>"; echo "\<ol\>"; foreach ($iterator as $value) { $counter++; print("\<li\>".$value.PHP\_EOL."\</li\>"); if($counter == 500) { break; } } echo "\</ol\>"; echo "\</pre\>";

In this simple example we created a new instance of the Infinite Iterator passing an array iterator to the constructor then we iterated over it and display each item. After that we added the termination condition like that:

if($counter == 500) { break; }

If you remove the termination condition the loop will continue and the browser will crash.

Limit Iterator

The limit iterator is another iterator that always used alongside the infinite iterator and it’s mostly like the limit clause in the mysql database, in other words it allows to iterate over a subset of items in iterator.

LimitIterator extends IteratorIterator implements OuterIterator { /\* Some methods \*/ public \_\_construct ( Iterator $iterator [, int $offset = 0 [, int $count = -1]] ) public mixed current ( void ) public Iterator getInnerIterator ( void ) public int getPosition ( void ) public mixed key ( void ) public void next ( void ) public void rewind ( void ) }

The limit iterator constructor takes three parameters:

  • The iterator object
  • the starting offset, if not included it will default to 0.
  • The count of items to limit, if not included it will default to all collection until end.

An example to illustrate the limit iterator:

\<?php // Create an iterator to be limited $programming\_languages = new ArrayIterator(array('C++', 'PHP', 'C#', 'Java', 'Swift')); // Loop starting from the third item and get 3 items echo "\<pre\>"; echo "\<ol\>"; foreach (new LimitIterator($programming\_languages, 2, 3) as $langauge) { print("\<li\>".$langauge.PHP\_EOL."\</li\>"); } echo "\</ol\>"; echo "\</pre\>"; echo "\<hr/\>"; // Loop starting from second item until the end // Note: offset starts from zero echo "\<pre\>"; echo "\<ol\>"; foreach (new LimitIterator($programming\_languages, 1) as $langauge) { print("\<li\>".$langauge.PHP\_EOL."\</li\>"); } echo "\</ol\>"; echo "\</pre\>";

Also if you remember from above when we said that the infinite iterator needs a termination condition, we can use the limit iterator as the termination condition with the infinite iterator so we can modify the above example like so:

\<?php $programming\_languages = array('C++', 'PHP', 'C#', 'Java', 'Swift'); $iterator = new InfiniteIterator(new ArrayIterator($programming\_languages)); echo "\<pre\>"; echo "\<ol\>"; foreach (new LimitIterator($iterator, 0, 500) as $value) { print("\<li\>".$value.PHP\_EOL."\</li\>"); } echo "\</ol\>"; echo "\</pre\>";


Glob Iterator

The glob iterator as it’s name implies inherits the behavior of the php function glob() to loop over the filesystem files and directories.

GlobIterator extends FilesystemIterator implements SeekableIterator , Countable { /\* Some constants \*/ const integer FilesystemIterator::CURRENT\_AS\_PATHNAME = 32 ; const integer FilesystemIterator::CURRENT\_AS\_FILEINFO = 0 ; const integer FilesystemIterator::CURRENT\_AS\_SELF = 16 ; const integer FilesystemIterator::CURRENT\_MODE\_MASK = 240 ; /\* Some methods \*/ public \_\_construct ( string $pattern [, int $flags = FilesystemIterator::KEY\_AS\_PATHNAME | FilesystemIterator::CURRENT\_AS\_FILEINFO] ) public int count ( void ) /\* Some inherited methods \*/ public mixed FilesystemIterator::current ( void ) }

As shown in the class structure the glob iterator extends from the File system iterator so each property and method in the File system iterator is also applicable in the glob iterator.

The glob iterator is almost like the glob() function as shown in the below example:

\<?php // using globe to list all jpg files foreach (glob("\*.jpg") as $filename) { echo "$filename size " . filesize($filename) . "\n"; } echo "\<hr/\>"; // using GlobIterator to list all jpg files $images = new GlobIterator("\*.jpg"); echo "\<pre\>"; echo "Number of images: " . $images-\>count() . PHP\_EOL; foreach ($images as $image) { echo $image . PHP\_EOL; } echo "\</pre\>";

As shown in the example above the GlobIterator constructor takes a pattern to search for files in the same way as glob().

Another example to retrieve all files alongside other various information, useful if you need to build a file manager in a web UI:

\<?php set\_time\_limit(0); // list all files $files = new GlobIterator("\*"); echo "\<pre\>"; echo "Number of files: " . $files-\>count() . "\n"; echo "\<ul\>"; foreach ($files as $file) { echo "\<li\>\<h2\>".$file-\>getFilename()."\</h2\>\<br/\> Extension: ".$file-\>getExtension()." Basename: ".$file-\>getBasename()." Size: ".$file-\>getSize()." bytes is Directory :".($file-\>isDir()?"yes":"no")." is File :".($file-\>isFile()?"yes":"no")." is Writable :".($file-\>isWritable()?"yes":"no")." is Readable :".($file-\>isReadable()?"yes":"no")." is Executable :".($file-\>isExecutable()?"yes":"no")." \<hr/\> \</li\>"; } echo "\</ul\>"; echo "\</pre\>";

Note that some methods here may throw exception like that:

Fatal error: Uncaught RuntimeException: SplFileInfo::getSize(): stat failed for

To solve this exception you need to make sure that the php.ini directive upload_max_filesize and post_max_size has a large value and also post_max_size must be larger than upload_max_filesize.

NoRewind Iterator

In the *NoRewind iterator * the rewind method never called in the beginning of the iteration or when it’s reversed which means that this iterator never rewound.

NoRewindIterator extends IteratorIterator { /\* Some methods \*/ public \_\_construct ( Iterator $iterator ) public mixed current ( void ) public iterator getInnerIterator ( void ) public mixed key ( void ) public void next ( void ) public void rewind ( void ) public bool valid ( void ) /\* Some inherited methods \*/ public IteratorIterator::\_\_construct ( Traversable $iterator ) public mixed IteratorIterator::current ( void ) }

To illustrate this behavior consider this example:

\<?php set\_time\_limit(0); $places = new ArrayIterator(["USA", "Germany", "France", "Turkey", "England"]); $iterator = new NoRewindIterator($places); foreach ($iterator as $key =\> $value) { echo "Key: ".$key."----"; echo "Value: ".$value."\<br/\>"; } $iterator-\>rewind(); echo "\<hr/\>"; foreach ($iterator as $key =\> $value) { echo "Key: ".$key."----"; echo "Value: ".$value."\<br/\>"; }

If you run the above example you note that the first foreach only executes and output the values but after calling $iterator->rewind() nothing happens and this is because rewind here didn’t reset the loop cursor to be at the beginning.

\<?php \<?php $programming\_languages = array("PHP", "Java", "Go", "Swift"); $noRewindIterator = new NoRewindIterator(new ArrayIterator($programming\_languages)); echo $noRewindIterator-\>current() . "\n"; $noRewindIterator-\>next(); // now rewind the iterator (nothing should happen) $noRewindIterator-\>rewind(); echo $noRewindIterator-\>current() . "\n"; ?\> // output PHP Java


In this tutorial of this series (PHP Iterators) we covered four more SPL Iterators, The infinite iterator to execute some code infinitely, the limit iterator to work on limited set of collection, the glob iterator to work of filesystem and the noRewind iterator.

The post PHP Iterators Part 4: SPL Infinite, Limit, Globe and NoRewind Iterators appeared first on Web and Mobile Tutorials.

Discussion (0)