Browsing folders and filtering files has never been easier with the PHP5 SPL

Another great classic when creating a site is the browsing of folders on the hard drive in search of files. Since PHP 5.3, the SPL has been enriched with classes allowing you to browse folders and add filters to select only certain files. In this article I offer you basic examples to understand the functioning of the PHP classes of the SPL.

Let's imagine this folder structure and the files as the basis for the examples:

_ theme
    |__ css
             |__ front.css
             |__ back.css
    |__  images
             |__ header.jpg
             |__ logo.png
             |__ rss_tag.png
             |__ mainmenu.jpg

1. Read all files in a folder

Browsing a folder is very simple to implement with the FileSystemIterator class. just instantiate the class by giving the path of the folder to browse and then use foreach to loop over each element of the folder.

<?php
 
$themeDir = __DIR__.'/theme';
$cssDir = $themeDir.'/css';
$imagesDir = $themeDir.'/images';
 
$iterator = new FilesystemIterator($themeDir, FilesystemIterator::SKIP_DOTS);
 
foreach($iterator as $file) {
    echo $file->getfilename()."\n";
}
 

The $file variable is an instance of the SplFileInfo object. The result of this function will print css and images. To list the contents of the images folder, replace the $themeDir variable by $imageDir when instaciating the FileSystemIterator class.

2. Recursively read all files in a folder

Listing all the files contained in the subfolders is done using the RecursiveDirectoryIterator and RecursiveIteratorIterator classes.

<?php
 
$themeDir = __DIR__.'/theme';
 
$iterator = new RecursiveDirectoryIterator($themeDir, FilesystemIterator::SKIP_DOTS);
 
foreach(new RecursiveIteratorIterator($iterator) as $file) {
    echo $file->getfilename()."\n";
}
> php exemple.php
back.css
front.css
logo.png
mainmenu.png
header.jpg
rss_tag.png
 

The RecursiveDirectoryIterator class extends FileSystemIterator and requires the use of the RecursiveIteratorIterator iterator. Without the use of this iterator, we will get the same result as with the FileSystemIterator class alone.

3. List PNG files only

As we saw above, the FileSystemIterator and RecursiveDirectoryIterator classes list all the files without difference. It is possible to add a filter that will restrict the result thanks to the FilterIterator class. I'm going to create a new class that will extend FilterIterator.

<?php
class pngFileFilterIterator extends FilterIterator
{
    public function accept(): bool
    {
        $sFileInfo = $this->getInnerIterator()->current();
 
	return (preg_match('#\.png$#', $sFileInfo));
    }
}
 

I've overridden the accept() method which should return a boolean. On the first line of the method I access the current element of the internal iterator.
It is now necessary to take this class into account when browsing files.

<?php
 
require 'filter.php';
 
$themeDir = __DIR__.'/theme';
 
$iterator = new RecursiveDirectoryIterator($themeDir, FilesystemIterator::SKIP_DOTS);
$recursiveIterator = new RecursiveIteratorIterator($iterator);
 
foreach(new pngFileFilterIterator($recursiveIterator) as $file) {
    echo $file->getfilename()."\n";
}
> php exemple.php
logo.png
mainmenu.png
rss_tag.png

All you have to do is pass the iterator to the filter constructor for the result to be restricted.

4. Only list files larger than 10KB

It's the same principle as above but this time we're going to tell the RecursiveDirectoryIterator class that we want a SplFileInfo object as output.

<?php
class bigFileFilterIterator extends FilterIterator
{
    public function accept(): bool
    {
        $oFileInfo = $this->getInnerIterator()->current();
 
        return ($oFileInfo->getSize() > 10000);
    }
}
<?php
 
require 'filter2.php';
 
$themeDir = __DIR__.'/theme';
 
$iterator = new RecursiveDirectoryIterator($themeDir, FilesystemIterator::SKIP_DOTS);
$iterator->setFlags(FilesystemIterator::CURRENT_AS_FILEINFO); // <--   new line
 
$recursiveIterator = new RecursiveIteratorIterator($iterator);
 
foreach(new bigFileFilterIterator($recursiveIterator) as $file) {
    echo $file->getfilename()."\n";
}
> php exemple.php
back.css
front.css
logo.png
mainmenu.png


Again the Simple PHP Library saves development time and stays in an OOP approach rather than having to write lengthy procedural scripts with the more classic PHP functions. In addition it is possible to stack filters; start by filtering png images, then add a filter to obtain only images larger than 10ko for example.

Add a comment