Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

LISTING D'UN RÉPERTOIRE AVEC FILTRES


Information sur la source

Catégorie :Class et Objet ( POO ) Classé sous : poo, itérateurs, parcours, listing, répertoire Niveau : Initié Date de création : 19/12/2007 Date de mise à jour : 28/05/2009 11:11:01 Vu / téléchargé: 3 949 / 238

Note :
9,33 / 10 - par 3 personnes
9,33 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (13)
Ajouter un commentaire et/ou une note

Description

Salut,

Je commençais à en avoir un peu marre de voir des sources ou des portions de codes (dans le forum) toujours en procédural (style PHP 3 ou 4), sans jamais utiliser d'itérateurs. Comme c'est le genre de source qui revient régulièrement, il faut prendre le problème à la base...
Alors maintenant, plus aucune excuse. Si vous avez PHP5.1 et que vous utilisez encore une boucle immonde du genre :
while (false !== ($file = readdir($handle))) {
// Blabla
}
ben faut penser à passer la seconde et à embrayer.

Il s'agit là d'un petit package permettant de parcourir un répertoire en 3 lignes de code, de manière récursive, avec possibilité de mettre des filtres (type, date, taille, extension, fichier, répertoire, expression régulière, etc) que l'on peut combiner.

Ce package de classes est (il me semble) enfantin à utiliser. Si on sait faire un foreach sur un tableau,on peut s'en sortir haut la main, les doigts dans l'nez et la tête dans l'c..
Il ne s'agit que d'un outil pour aider à parcourir un répertoire récursivement, pas d'un truc tout fait qui affiche du html dégueulasse avec des tableaux et des compteurs de lignes pas possibles (non mais on voit d'ces trucs des fois...). A vous de gérer l'affichage de la sortie.
 

Source

  • <?php
  • # Inclusion des fichiers nécessaires, définitions des classes, et tout le tremblement
  • require_once('/path/to/xdir/init_xdir.php');
  • # Notre itérateur
  • $oDir = new XDir('/home/user/docs');
  • # Ne lister que les fichiers modifiés depuis une semaine
  • $oDir -> addFilter('mtime', strtotime('-1 week'));
  • # Ne lister que les fichiers audio
  • $oDir -> addFilter('audio');
  • # On boucle
  • foreach ($oDir as $oFile) {
  • echo $oFile -> getFilename() . '<br />'; //
  • }
  • ?>
<?php

# Inclusion des fichiers nécessaires, définitions des classes, et tout le tremblement
require_once('/path/to/xdir/init_xdir.php');

# Notre itérateur
$oDir = new XDir('/home/user/docs');

# Ne lister que les fichiers modifiés depuis une semaine
$oDir -> addFilter('mtime', strtotime('-1 week'));

# Ne lister que les fichiers audio
$oDir -> addFilter('audio');

# On boucle
foreach ($oDir as $oFile) {
  echo $oFile -> getFilename() . '<br />'; //
}
?>

Conclusion

Le code source est documenté à outrance (format phpDoc + commentaires au fil du code).
Un fichier README donne les base pour utiliser la classe.
Le fichier Filters.txt explique en détail (de manière plutôt exhaustive) le fonctionnement de chaque filtre. Il explique également comment écrire de nouveaux filtres (tiens j'y pense : j'ai pas fait de filtre pour le propriétaire ou le groupe, ou les permissions... à faire donc...).
Le bazar était en GPLv2, il passe en GPLv3, et mes classes ont un peu changé de nom (j'ai appelé ce package XDir, pour eXtended Directory Recursive Iterator).

J'aimerais avoir l'avis de personnes se considérant comme "débutantes" ou "néophytes" quant à la facilité de prise en main. Je m'interroge surtout sur l'utilisation des items obtenus lors de l'itération, qui sont des instances d'une classe héritant de SplFileInfo... Pas sûr que ça parle à tout le monde, finalement... Donc s'il faut faire de la doc là dessus, pas de problème, si ça peut aider les débutants à lâcher un peu la grappe à opendir() et readdir()... je suis prêt à pas mal de sacrifices :)
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Historique

22 décembre 2007 22:03:43 :
Suppression d'une référence à un fichier inexistant
28 mai 2009 11:11:02 :
Grosse mise à jour du bazar

Commentaires et avis

signaler à un administrateur
Commentaire de Dexmon le 22/12/2007 20:21:19

J'ai une erreur relative à un fichier manquant:
Warning: require_once(/usr/local/www/html/www/clients/fxp/core/config.inc.php) [function.require-once]: failed to open stream: No such file or directory in /usr/local/www/html/www/clients/fxp/fxp.inc.php on line 5

Fatal error: require_once() [function.require]: Failed opening required '/usr/local/www/html/www/clients/fxp/core/config.inc.php' (include_path='.:/usr/local/lib/php:/usr/local/share/pear:/usr/local/www/html/pastebin/lib') in /usr/local/www/html/www/clients/fxp/fxp.inc.php on line 5

le fichier config.inc.php ne se trouve pas dans l'archive!!!

signaler à un administrateur
Commentaire de neigedhiver le 22/12/2007 22:01:41

Au temps pour moi... Le fichier est inutile, il suffit de supprimer la ligne qui y fait référence.
Je mets à jour l'archive.

signaler à un administrateur
Commentaire de xaraan le 23/12/2007 14:18:42 8/10

Après inspection de la source, voici quelques critiques.

Dans le fichier fxp/fxp.inc.php tu ouvres une session (session_start). Tu devrais tester si la session est déjà ouverte afin de ne pas provoquer d'erreurs si quelqu'un décide d'utiliser ton code. Je te conseille d'utiliser des espaces de nommage pour tes sessions afin de ne pas écraser d'éventuelles autres sessions existantes.

Ton fichier fxp/core/functions.inc.php ne sert pas vraiment. Je te conseillerais d'inclure ce code dans fxp/fxp.inc.php. Pour ce qui est de la fonction fxp_import_classes(), je te conseillerais de ... ne pas utiliser un fichier XML mais de charger tes classes en dur. Si tu veux tout de même utiliser du XML, mets en place un système de cache afin de ne pas charger et parser le fichier XML à chaque appel ! Les fichiers __init__.php c'est moche. Tu inclus un fichier qui fait des inclusions, autant inclure directement les fichiers cibles. Tu y gagneras en performances.

Là, ça va saigner ... fxp/core/classes/FxpFileInfo/FxpFileInfo.class.php et fxp/core/classes/FxpFileInfo/extensions.xml sont deux monstruosités ! Certes le code n'est pas trop mal mais c'est un gouffre à performance ! Le fichier XML ne fait pas moins de 1100 lignes et tu ne mets même rien en cache. De plus, XPath c'est fantastique, mais ça consomme aussi énormément de ressources. Je ne serais que trop te conseiller de revoir cette partie du traitement.

Sinon pas grand chose à dire sur le reste, que du bon.

Joyeux Noël :)

signaler à un administrateur
Commentaire de neigedhiver le 23/12/2007 14:48:31

Salut Xaraan,

Merci pour tes remarques. Je vais répondre pour justifier quelques pratiques dans mon code.

Comme je le dis dans mon fichier README, ces classes font partie d'une application en cours de développement : un explorateur de fichiers. C'est pas le genre d'application multiutilisateurs avec 250 accès par seconde... Donc les performances, c'est pas la priorité (tant que la page ne met pas 3 h à s'afficher).

Pour la session, c'est un oubli : je vais l'enlever, elle ne sert à rien pour ces classes seules, elle fait partie du reste de l'application.

Le fichier de fonctions : oui, il ne sert pas à grand chose puisqu'il n'y a qu'une seule fonction. Mais encore dans le cadre de l'application complète, il a vocation à être étoffé. Pour sortir les classes du package, je ne me voyais pas tout réorganiser : juste supprimer ce qui n'est pas utile.

Les fichiers __init__ : tu trouves ça moche, moi je trouve ça très pratique. Parce que le fichier se charge (ahah) de charger les fichiers nécessaires au bon fonctionnement d'une classe. Dans ma méthode de développement, mon organisation, chaque classe se trouve dans un répertoire du même nom. Je n'utilise pas l'autoload pour ne pas forcer une application tierce (dans le cas d'une intégration de l'application, je veux dire l'explorateur ou autre chose) à utiliser les mêmes conventions d'autochargement. Ma fonction de chargement de classes fait ça très bien.
J'ai donc utilisé un fichier XML pour les classes à charger : parce que c'est plus pratique à modifier à la main.
Encore une fois, les performances que ça coûte là sont franchement insignifiantes pour l'utilisation de l'application.
Si on veut intégrer uniquement ces classes dans une application multi-utilisateur avec de plus nombreux accès, on peut changer ça. Mais je ne suis pas certain que les performances perdues soient si importantes que ça.

Quand au fichier XML des extensions, j'ai du mal à voir où est réellement le problème : le fichier XML n'est pas lu intégralement, il est juste chargé. Il ne me semble pas que SimpleXML parse le fichier dans son intégralité lors du chargement. Il me semble que, justement, il le parcours quand on itère dessus.
La requête xPath est peut-être lourde (d'autant qu'elle cherche un élément d'après la valeur d'un attribut), mais j'ai du mal à voir comment on peut l'alléger. Mettre en cache : je ne vois pas l'utilité, si le fichier n'est pas parsé lorsqu'il est chargé. Donc que le fichier fasse 20 ou 1000 lignes, la principale différence réside dans l'espace mémoire alloué.
Mais je me trompe peut-être sur le chargement d'un objet SimpleXML (vais creuser de ce côté là).
Autrement, mettre en cache dans un tableau PHP, ça implique que, pour le coup, l'intégralité du fichier est parcouru lors du chargement. Je ne vois pas ce qu'on y gagne.

Mais je le concède : certains ici sont bien plus aptes que moi à évaluer les différences de performances dans un cas ou un autre.

Si tu as quelque chose à me proposer pour améliorer ça, je suis preneur.

En quoi FxpFileInfo.class.php est une monstruosité ? Tu dis ça à cause de l'utilisation du fichier xml ? Ou bien... ? Si tu peux développer...

signaler à un administrateur
Commentaire de xaraan le 23/12/2007 16:37:15

Neigedhiver, pour ce qui est de SimpleXML, je vais chercher du côté de la remarque que tu as faite moi aussi.

Pour ce qui est de la classe FxpFileInfo je parlais du fait qu'elle se base sur un XPath pour obtenir les données dont elle a besoin. L'idée est bonne dans le cas où SimpleXML fonctionne comme tu le penses. Le problème est qu'XPath va parcourir ton objet SXE et filtrer chacun des noeuds afin de trouver celui recherché. Or, une fois encore je me base sur mon propre avis et non des données techniques puisque je les ignore, je ne pense pas que le fichier XML soit indexé, mappé ou hashé, surtout si on part du principe qu'il est lu "au fut et à mesure que nécessaire". Auquel cas, les itérations de XPath se verront de plus en plus longues en fonction de la profondeur de ton arbre XML.

Je n'ai pas pris la peine de lire le README lors de mon premier commentaire, mais tu as raison. Si ce code sert seulement à un explorateur, il n'est pas utile de mettre en cache les données à la vue de la faible utilisation des pages. Toutefois, si ce code a été posté c'est pour être partagé voire réutilisé par d'autres développeurs qui eux, devront implémenter du cache et modifier tes classes peut être ! Voila pourquoi j'avais émis l'hypothèse du système de cache, permettre aux autres développeurs d'utiliser tes classes sans avoir à trop se soucier des performances associées.

Ta remarque sur le tableau en cache n'est pas juste. Le tableau n'a pas besoin d'être parsé au même titre qu'un fichier XML ! De plus, il est indexé ce qui accélère la recherche de données pour un offset donné, contrairement à XPath.

Pour en revenir aux fichiers __init__.php, puisque tu utilises des fichiers XML pour charger en quelques sortes les paquetages principaux puis les classes associées, pourquoi ne pas simplement combiner tes fichiers __init__ et XML pour charger toutes les classes en une seule fois, via un seul fichier XML ?

J'espère que tu ne vois pas mes commentaires comme des critiques négatives car ton code est très bon à mon sens.

signaler à un administrateur
Commentaire de neigedhiver le 23/12/2007 16:55:49

Non non, je te rassure, je ne le vois pas du tout comme des critiques négatives. Je le vois comme des critiques constructives.
Tu m'aurais dit "C'est pourri", je ne te cache pas que j'aurais été très désagréable. Simplement, mes réponses voulaient justifier certains choix faits  dans mon développement.

Pour ce qui est de xpath, je pense que ce qui peut être mis en cache, ce sont les informations récupérées. Lors de la première requête xpath, on lit le xml. Si on doit à nouveau lister un fichier de la même extension, on va exécuter à nouveau la requête xpath, ce qui du coup, peut tout à fait être allégé : on stocke les informations de l'extension dans un tableau. Si l'extension a déjà été "lue", on va certes plus vite en récupérant la valeur dans le tableau qu'en réexécutant une requête xpath.
Ca allège d'autant plus que le fichier est volumineux, que le nombre de fichiers listés est important, et que certaines extensions sont récurrentes.
Donc je vais implémenter ça. Merci d'avoir attiré mon attention sur ce point.

Je reste persuadé (mais je ne sais pas comment le vérifier) que SimpleXML se contente de charger en mémoire un fichier XML, lors de son instanciation. Il ne le parse que lorsqu'il le lit. Mais en même temps que j'écris, je suis pris d'un doute... SimpleXML est quand même capable de vérifier que le fichier XML chargé est bien formé... Je suis pas assez calé en C pour aller fouiller dans les sources de l'extension... Mais je pense que l'information vaut la peine d'être connue.

Pour ce qui est des fichiers __init__, je me suis inspiré du chargement des classes en Python. En fait, je considère chaque répertoire comme un package indépendant. Tu noteras que si j'avais considéré chaque répertoire comme une classe, j'aurais fait un répertoire pour la classe filtre. Or je considère que les filtres font partie intégrante du package FxpDirectoryIterator.

L'idée, dans une vision globale de l'architecture d'un site web, est que dans le fichier classes.xml on ne déclare que les packages que l'on souhaite utiliser. Ce qui laisse libre le nom des fichiers de chaque classe, la gestion des déclarations au sein d'un package (nom de la classe pour le fichier, plusieurs classes par fichier, etc). Chaque package possède son propre fichier __init__, qui est appelé pour le charger (comme en python) : ce fichier peut ne faire qu'inclure d'autres fichiers, mais il peut aussi être utilisé pour faire des vérifications (par exemple, l'existance ou non d'une classe, comme pour DirectoryIterator).
Tu noteras que l'ordre de déclaration des classes est important : si tu déclares une interface après la classe qui l'implémente, lors de la définition de la classe, un message d'erreur survient pour signaler que l'interface n'existe pas. Cela permet de s'assurer, dans le __init__ que les classes sont déclarées dans le bon ordre.

signaler à un administrateur
Commentaire de neigedhiver le 23/12/2007 17:03:46

Mince j'ai validé trop vite, j'ai encore des choses à dire (Alzheimer, quand tu nous tiens).

J'ai développé ces classes dans le but de les intégrer à un explorateur. L'idée était de proposer un explorateur PHP5, orienté objet (alors que tout ce qu'on voit d'ordinaire n'est que du procédural PHP3).
J'ai voulu publier ces classes séparément pour deux raisons :
- le développement de l'explorateur est bien plus long que le développement de ces quelques classes : tout ce qui est interface graphique (IHM), Ajax, c'est pas mon fort. Je suis plus doué pour le traitement abstrait...
- j'en avais franchement ras le bol de voir des parcours de répertoires avec toujours la même boucle while (et encore, quand les gens font l'effort de l'écrire correctement, comme décrite dans la doc, ce qui est rarement le cas).
C'est donc aussi, pour beaucoup, un package à but didactique : oui, on peut parcourir un répertoire et afficher toutes les informations des fichiers, les filtrer, avec quelques lignes, faciles à lire.

Ces classes peuvent certainement être utilisées dans un autre but que d'être le coeur d'un explorateur. A ce moment là, la classe FxpFileInfo sert très peu. Ca me fait penser qu'il faut que je permette, lors de l'instanciation de FxpDirectoryIterator, de paramétrer ce qu'on souhaite obtenir avec la méthode getFileInfo(). En effet, la classe RecursiveDirectoryIterator prévoit que getFileInfo() peut retourner soit le résultat de getPathname(), soit un nouvel objet SplFileInfo... Pour un simple listing de répertoire, on peut se contenter de getPathname()...

Ca me fait donc deux choses à rajouter...

signaler à un administrateur
Commentaire de xaraan le 24/12/2007 12:36:46

Bonne continuation alors pour ton explorateur et n'hésite pas à nous tenir au courant de ton avancement ! Et je confirme, SimpleXML lit bien tout le fichier lors de l'instanciation.

signaler à un administrateur
Commentaire de malalam le 26/12/2007 19:38:31 administrateur CS

Hello,

pour en remettre une couche sur le XML... :-) SimpleXML charge en effet tout le fichier ET le parse.
Mais le problème n'est pas vraiment de savoir si c'est très gourmand ou non. C'est surtout lié à l'utilisation que l'on en fait. XPath est extrèmement puissant, et poour une structure complexe, avec des recherches potentielles complexes, il est largement préférable d'implémenter du XML et XPath, qui feront ça en natif (LIBxml est écrit en C) plutôt que de créer un moteur de recherche dans un tableau multidimensionnel en PHP. Ce sera forcément bcp plus simple et bcp plus souple...et bcp plus rapide. Un tableau aussi est chargé en mémoire intégralement, selon comment on l'utilise.
Si on veut optimiser, il faut combiner XMLReader, qui fait du pull (c'est un itérateur, quoi). Mais il ne permettra pas de faire des requêtes XPath. Néanmoins, si on a des requêtes XPath à faire sur un noeud précis et connu du document xml, on peut très bien d'y déplaxer avec XMLReader, puis récupérer le noeud et le passer à SimpleXML, qui ne chargera donc que cette partie, et là, déclencher notre requête XPath.
Il y a aussi la possibilité de voir du côté de SimpleXMLIterator, dans la SPL.

signaler à un administrateur
Commentaire de neigedhiver le 26/12/2007 22:50:03

Salut Boss,

Merci pour tes précisions.
Dans la mesure où j'ai besoin d'avoir toutes les extensions chargées et facilement accessibles, il me semble nécessaire de charger l'intégralité du contenu. Et à part en utilisant un objet SimpleXML, je ne vois pas comment faire... Un tableau PHP, avec la bonne clé, permettrait un accès rapide. Mais plus rapide que XPath ? Je ne sais pas. Et je ne me sens pas le courage de bencher chaque méthode.

Pour l'heure, j'ai apporté une correction (pas encore en ligne, et c'est pas pour tout de suite, n'étant pas chez moi pour une dizaine de jours) qui met en cache les informations des extensions (obtenues avec une requête XPath) dans un tableau (une variable statique de la classe FxpFileInfo). Ainsi, si on liste un répertoire ne contenant que des fichiers txt, la requête XPath n'est exécutée qu'une fois, les informations pour l'extension étant ensuite chargées depuis le tableau (ce qui devrait, quand même, être plus rapide avec un truc du genre $tableau['txt']['mime']). Si c'est pas plus rapide, je laisse comme c'était.

Concernant SimpleXMLIterator, j'y avais bien pensé (forcément, je cherche à utiliser la SPL au maximum). Seulement, ça ne me sert pas dans mon cas : je n'ai pas besoin de dresser une liste du contenu de mon fichier xml, mais d'accéder à n'importe quel élément à tout moment.

Bon. Voilà où j'en suis pour l'instant.

En tout cas, c'est le genre de débat dont je rafole... Donc n'hésitez pas à apporter des précisions de toute sorte quant à une optimisation possible. C'est intéressant pour le code, mais aussi et SURTOUT pour la culture geek (culture générale de développeur).

Encore merci pour les commentaires, et bonne fêtes de fin d'année.

signaler à un administrateur
Commentaire de codefalse le 10/06/2009 22:42:02 administrateur CS 10/10

C'est rare du code de cette qualitée ...

signaler à un administrateur
Commentaire de malalam le 10/06/2009 22:42:18 administrateur CS 10/10

ah j'avais pas noté ?

signaler à un administrateur
Commentaire de neigedhiver le 10/06/2009 22:44:23

MDR

Vos m'faites marrer les gars, putain...

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

Fichier INDEX auto-exécutable [ par BSide ] BSideBonjour,j'utilise EasyPHP1.6.Habituellement, quand je veux exécuter un script PHP, je vais sur le web local, je sélectionne le répertoire qui m'i probleme parcours fichier [ par TRASH52 ] TRASH52En fait j'ai testé des trucs avec les fonctions chdir, mkdir mais je n'arrive pas à voir ou je me situe!j'aimerai si possible, qu'on sous-repertoire fichier ............ [ par TRASH52 ] TRASH52bon je vous met le code!En fait, je voudrais que mon programme a partir d'u ftp_get php [ par CC24 ] bonjour à tous !est-ce que l'un d'entre vous pourrait m'indiquer la syntaxe à utiliser pour télécharger un fichier situé dans un sous-répertoire du ré Rechercher capacité d'un répertoire sur un serveur [ par twiems ] TwiemsJe souhaite rechercher et afficher la capacité d'un répertoire sur le serveur auquel mon pc est connecté.Y a t il une fonction ou une procédure Supprimer les .html d'un répertoire [ par twiems ] Twiems:PJe souhaiterais supprimer tous les fichiers d'extension .html d'un dossier nommé chambre mais je n'y parvient pas.Si vous pouviez m'aider je v Probleme de création et de copie de Répertoire [ par jdaviaud ] Voila, dans mon script, j'utilise les deux fonctions suivantes pour copier le contenu d'un répertoire avec creation du nouveau répertoire de destinati Protection de l'adresse de mon répertoire de téléchargement : solution $HTTP_REFERER [ par 1motorola1 ] Salut à tout le monde !Alors voila je tente ces derniers temps d'éviter que les visiteurs de mon site puisse connaitre le répertoire ou se situe les f affichege d'image [ par lumikele ] Bonjour,je suis surement le plus débutant des débutant puisque jusqu'à 10 mn, je ne connaissais pas la php :-(J'ai fait plusieurs choses en html mais Probleme listing avec mysql [ par zzzzzz ] Yep j'aimerai lister un champ nick par nom donc je fait ca avec mysql. mais il y a comme euh un probca me liste dans cet ordre:Diablusmembres10membres


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,655 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.