Parcourir des dossiers et filtrer les fichiers n'a jamais été aussi simple avec la SPL de PHP5
Un autre grand classique lors de la création d'un site, c'est le parcours des dossiers du disque dur à la recherche de fichiers. Depuis PHP 5.3, la SPL s'est enrichie de classes permettant de parcourir les dossiers et d'ajouter des filtres pour ne sélectionner que certains fichiers. Dans cet article je vous propose des exemples basiques pour comprendre le fonctionnement des classes PHP de la SPL.
Imaginons cette structure de dossier et les fichiers comme base pour les exemples:
_ theme |__ css |__ front.css |__ back.css |__ images |__ header.jpg |__ logo.png |__ rss_tag.png |__ mainmenu.jpg
1. Lire tous les fichiers d'un dossier
Le parcours d'un dossier est très simple à mettre en oeuvre avec la classe FilesystemIterator. il suffit d'instancier la classe en donnant le chemin du dossier à parcourir puis d'utiliser foreach pour boucler sur chaque élément du dossier.
<?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"; }
La variable $file est une instance de l'objet splFileInfo. Le résultat de cette fonction va imprimer css et images. Pour lister le contenu du dossier images, il faut remplacer la variable $themedir par $imagedir lors de l'instaciation de la class FilesystemIterator.
2. Lire tous les fichiers d'un dossier de manière récursive
Lister tous les fichiers contenus dans les sous dossiers se fait à l'aide des classes RecursiveDirectoryIterator et RecursiveIteratorIterator.
<?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
La classe RecursiveDirectoryIterator étend FilesystemIterator et nécessite l'utilisation de l'iterateur RecursiveIteratorIterator. Sans l'utilisation de cet iterateur, on obtiendrai le même résultat qu'avec la classe FilesystemIterator seule.
3. Lister uniquement les fichiers PNG
On l'a vu au dessus, les classes FilesystemIterator et RecursiveDirectoryIterator listent tous les fichiers sans différence. Il est possible d'ajouter un filtre qui va restreindre le résultat grâce à la classe FilterIterator. Je vais créer une nouvelle classe qui va étendre FilterIterator.
<?php class pngFileFilterIterator extends FilterIterator { public function accept(): bool { $sFileInfo = $this->getInnerIterator()->current(); return (preg_match('#\.png$#', $sFileInfo)); } }
J'ai surchargé la méthode accept() qui doit retourner un boolean. Sur la première ligne de la méthode j'accède à l'élement courant de l'itérateur interne.
Il faut maintenant prendre en compte cette classe lors du parcours des dossiers.
<?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
Il suffit de passer l'iterator au constructeur du filtre pour que le résultat soit restreint.
4. Lister uniquement les fichiers de plus de 10ko
C'est le même principe qu'au dessus mais cette fois on va indiquer à la classe RecursiveDirectoryIterator que l'on veut un objet SplFileInfo en sortie.
<?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); // <-- nouvelle ligne $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
Encore une fois la Simple PHP Library permet de gagner du temps de développement et de rester dans une approche de POO plutôt que de devoir écrire de longs scripts procéduraux avec les fonctions plus classiques de PHP. De plus il est possible d'empiler les filtres; commencer par filtrer les images de type png, puis ajouter un filtre pour n'obtenir que les images de plus de 10ko par exemple.
Réponse de Ulrich le 4 janv. 2018