Gestion de fichiers avec la spl

Soyez le premier à donner votre avis sur cette source.

Vue 4 554 fois - Téléchargée 235 fois

Description

Voilà bien longtemps que je lis différentes choses à propose de la SPL dans ces pages et j'ai fini par retrousser mes manches et essayer de comprendre le fonctionnement de cet outil.
Déjà, pour ceux que ça intéresse d'en savoir plus, voilà un lien qui m'a bien aidé à démarrer : http://julien-pauli.developpez.com/tutoriels/php/spl/
Dans cette source, rien de bien transcendant, de quoi établir un listing complet d'un dossier et de ses sous-dossiers (fichiers inclus), possibilité d'appliquer des filtres, d'en ressortir un arbre HTML des dossiers et fichiers ou un Array type listing de fichiers.
Cette source est très basique mais je ne souhaitais pas aller plus loin pour le moment car mes connaissances de la SPL datent d'hier. Il y aura certainement des choses à corriger d'abord puis des fonctions à ajouter ensuite.
Merci aux grands gourous de nous donner leur avis (Malalam, Neigedhiver, ...) sur cette source qui souhaite apporter un peu de fraîcheur avec la SPL.
Merci d'éviter les réflexions du genre 'il vaudrait mieux mettre les noms des méthodes en anglais', ... c'est pas le but ici, hein !

---------------------------
Utilisation de la class et des fonctions présentent :

//--> On crée l'instance de la classe
$fichiers = new utilitaireFichiers('./');

//--> On définit un peu le style de l'arbre HTML.
$fichiers->arbreFichierDebut = "<li class='{class}'>{fichier} <span class='taille'>({taille})</span>\n";

//--> On filtre les fichiers pour ne garder que ceux qui sont d'une extension .css
$fichiers->filtreExtensions("css",true);

//--> On renvoie l'arbre HTML qui contient tous les dossiers mais seulement les fichiers css
echo $fichiers->arborescence();

//--> On reprend la liste complète
$fichiers->initListe();

//--> On ne sélectionne que les fichiers de type .js
$fichiers->filtreExtensions("js",true);

//--> On peut passer un deuxième filtre (ou plus). Ici pour n'afficher que les fichiers qui sont dans un dossier "module"
$fichiers->filtreRegExp("#/module/#i", 0, 0, 0, true);

//--> On récupère la liste des fichiers sous forme de tableau et on l'affiche pour contrôle
print_r($fichiers->arrayFichiers());

----------------------------------
A noter que j'utilise aussi ça pour la gestion de l'affichage de l'arbre :
$css = "<style type='text/css'>\n";
$css .= "ul {padding:0 0 10px 16px}\n";
$css .= "li.dossier {font-weight:bold}\n";
$css .= "li.fichier {font-weight:normal}\n";
$css .= "li .taille {font-size: 0.8em}\n";
$css .= "</style>\n";

Source / Exemple :


<?php

/*****************************************************
/*
/* Class de gestion des fichiers
/* Cette class permet pour le moment de gérer une liste de dossiers/fichiers grâce à la SPL
/* On peut y appliquer des filtres par extension de fichier et des filtres personnalisés
/* On peut retourner un arbre des dossiers en HTML ou une liste des fichiers dans un Array
/*
/* Cette class est dans un état basique et chacun peut le modifier à son grée. Le principe c'est 
/* que tout se passe en 3 temps
/* 1- On crée le pointeur principal et on récupère la liste complète des dossiers/fichiers
/* 2- On applique tous les filtres et les tris voulus
/* 3- On traite la liste obtenue, soit pour une récupération sous forme HTML, Array, ... , soit
/* pour appliquer des oppérations de suppression, renommage, ...
/*
/*****************************************************/

class utilitaireFichiers {
	
	private $racine;
	private $listeRacine;
	private $listeSelect;
	
	//--> Pour l'affichage de l'arbre HTML
	public $arbreDossierDebut	= "<ul>\n";
	public $arbreDossierFin		= "</ul>\n";
	public $arbreFichierDebut	= "<li>\n{fichier}\n";
	public $arbreFichierFin		= "</li>\n";
	
	/**

  • @brief création de la gestion des fichiers
  • @param $_racine chemin absolu ou relatif vers le dossier à gérer
  • /
public function __construct($_racine){ $this->racine = $_racine; $this->listeRacine = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->racine,RecursiveDirectoryIterator::KEY_AS_FILENAME), RecursiveIteratorIterator::SELF_FIRST); $this->listeSelect = $this->listeRacine; } /**
  • @brief gère l'affichage des dossiers/fichiers sous forme d'arbre avec les paramètres arbreDossierDebut, arbreDossierFin, arbreFichierDebut, arbreFichierFin
  • @return renvoie un arbre au format HTML
  • /
public function arborescence(){ $arbo = $this->arbreDossierDebut; $nivoAncien = $this->listeSelect->getDepth(); $typeAncien = ""; foreach ($this->listeSelect as $entry) { $nivoActuel = $this->listeSelect->getDepth(); if($nivoActuel < $nivoAncien || ($entry->isDir() && $nivoActuel == $nivoAncien)){ $boucle = $nivoAncien - $nivoActuel; if($typeAncien == "fichier") $boucle--; for($i=0;$i<=$boucle;$i++){ $arbo .= $this->arbreDossierFin . $this->arbreFichierFin; } } //--> Défini le type $type = $entry->isDir() ? "dossier" : "fichier"; //--> Calcul des valeurs $valeurs = array( "chemin" => $entry->getRealPath(), "fichier" => $entry->getFilename(), "taille" => $entry->getSize(), "class" => $type ); $chercher = array( "chemin" => "#{chemin}#i", "fichier" => "#{fichier}#i", "taille" => "#{taille}#i", "class" => "#{class}#i" ); //--> Création de la ligne d'affichage $arbo .= preg_replace($chercher, $valeurs, $this->arbreFichierDebut) . "\n"; //--> Si c'est un dossier et qu'il a des enfants, on ajoute le code de début de dossier if($type == "dossier" && $this->listeSelect->hasChildren()){ $arbo .= $this->arbreDossierDebut; } else { //--> Ajout de la fin de fichier $arbo .= $this->arbreFichierFin; } //--> Enregistrement du nivo actuel et du type $nivoAncien = $nivoActuel; $typeAncien = $type; } $arbo .= $this->arbreDossierFin; return $arbo; } /**
  • @brief reprend la liste complète des dossiers/fichiers
  • /
public function initListe(){ $this->listeSelect = $this->listeRacine; } /**
  • @brief filtrage des données ($this->listeSelect) avec une expression régulière. Possibilité de garder tous les dossiers
  • @param $_regex expression régulière
  • @param $_mode
  • @param $_flags
  • @param $_preg_flags
  • @param $_preservDir Mettre à true pour ne pas filtrer les dossiers. Permet ainsi de garder la structure des dossiers tout en filtrant les fichiers.
  • /
public function filtreRegExp($_regex, $_mode = 0, $_flags = 0, $_preg_flags = 0, $_preservDir = false){ if($_preservDir){ $this->listeSelect = new RegexIteratorPreservDir($this->listeSelect, $_regex, $_mode, $_flags, $_preg_flags); } else { $this->listeSelect = new RegexIterator($this->listeSelect, $_regex, $_mode, $_flags, $_preg_flags); } } /**
  • @brief Filtre les fichiers par leurs extensions. Fonction de facilité qui utilise en réalité le système de tri par RegExp
  • @param $_extensions Liste d'extensions séparées par des virgules. Ex: php,html,js
  • @param $_preservDir Mettre à true pour ne pas filtrer les dossiers. Permet ainsi de garder la structure des dossiers tout en filtrant les fichiers.
  • /
public function filtreExtensions($_extensions, $_preservDir = false){ $extensions = explode(",", $_extensions); $exp = "#\.(" . implode("|", $extensions) . ")$#i"; $this->filtreRegExp($exp, 0, 0, 0, $_preservDir); } /**
  • @brief fonction qui renvoie la liste des fichiers sous forme d'array
  • @return Array contenant la liste des chemins complets des fichiers
  • /
public function arrayFichiers(){ $fichiers = array(); foreach ($this->listeSelect as $entry){ if($entry->isFile()){ $fichiers[] = $entry->getRealPath(); } } return $fichiers; } } /**
  • @brief Class redéfinissant RegexIterator pour gérer la préservation des dossiers
  • /
class RegexIteratorPreservDir extends RegexIterator { public function __construct($_it, $_regex, $_mode = 0, $_flags = 0, $_preg_flags = 0){ parent::__construct($_it, $_regex, $_mode, $_flags, $_preg_flags); $this->regex = $_regex; $this->flags = $_flags; $this->mode = $_mode; $this->preg_flags = $_preg_flags; } /**
  • @brief On garde la fonction de base mais on ajoute la condition if($this->current->isDir())
  • /
public function accept(){ $matches = array(); $this->key = parent::key(); $this->current = parent::current(); if($this->current->isDir()){ return true; } else { $subject = ($this->flags & self::USE_KEY) ? $this->key : $this->current; switch($this->mode){ case self::MATCH: return preg_match($this->regex, $subject, $matches, $this->preg_flags); case self::GET_MATCH: $this->current = array(); return preg_match($this->regex, $subject, $this->current, $this->preg_flags) > 0; case self::ALL_MATCHES: $this->current = array(); return preg_match_all($this->regex, $subject, $this->current, $this->preg_flags) > 0; case self::SPLIT: $this->current = array(); preg_split($this->regex, $subject, $this->current, $this->preg_flags) > 1; case self::REPLACE: $this->current = array(); $result = preg_replace($this->regex, $this->replacement, $subject); if ($this->flags & self::USE_KEY){ $this->key = $result; } else { $this->current = $result; } } } } } ?>

Conclusion :


Quelques heures à étudier le fonctionnement de la SPL et déjà un bout de code fonctionnel. C'était pas si méchant que ça ... Je pense en avoir saisie une bonne partie. Pour le reste, des erreurs de fonctionnement sont peut-être à relever dans ce code. Merci aux experts de nous éclairer.

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
48
Date d'inscription
jeudi 18 octobre 2007
Statut
Membre
Dernière intervention
5 août 2009

Salut, heureusement que j ai plus de 20 minutes pour regarder ce site sinon je n aurais pas eu le temps de tout lire...
Moi j ai fais un bon en php il y a tout juste 1 mois peut etre moins en apprenant l'existence de la POO... Je ne savais rien encore la dessus auparavant. Et j ai lu beaucoup de tutoriaux sur le sujet. Et je n avais pas encore compris que les iterators pouvais servir a une arborescence et je vais de ce pas visiter ce lien sur la SPL...Merci a vous pour vos codes et commentaires judicieux. Je n ai pas encore ecris de source en PHP (seulement en Javascript). J'espere reussir un jour a ecrire de belles sources comme celle-ci.

PS:Je m excuse pour toutes les fautes d ortographe que je peux faire...
Messages postés
2483
Date d'inscription
jeudi 30 novembre 2006
Statut
Membre
Dernière intervention
14 janvier 2011
17
@Malalam : Ca va, et toi ? C'est pas facile de communiquer avec toi ;) Dernière fois que j'ai essayé de t'appeler, j'ai pas réussi (et pourtant j'avais une bonne excuse, c'était ton anniv...)

@Codefalse : Pour ce qui est de l'ancienneté de la SPL, tu te trompes un peu... Elle est compilée par défaut depuis PHP5.0. Depuis PHP5.3, elle ne peut pas être désinstallée. Et avant PHP5? la SPL était disponible comme extension PECL : http://pecl.php.net/package/SPL

Voilà, c'est tout ce que j'ai à rajouter pour le moment :).

Ah non, dernière chose... Ca fait vraiment plaisir de savoir que certaines personnes lisent quand même nos commentaires, nos longues discussions et interminables débats à l'occasion de sources de qualité variables, et en tirent des enseignements positifs... Ca conforte dans l'idée que les longues discussion parfois hors-sujet ne sont jamais vaines :)
Messages postés
1123
Date d'inscription
mardi 8 janvier 2002
Statut
Modérateur
Dernière intervention
21 avril 2009
1
Que dire ! Pas mal de choses ont déjà été mentionnée.
Je voulais ajouter un malus parce que mon pseudo était pas mentionné, mais tu te rattrape dans ton dernier message ... mais j'hésite quand même ... bon ok je blague :p

Pour ce qui est du MVC, je rejoint Neige et Malalam. Tu parle ensuite qu'en général, tu boucle sur un array.
J'aimerai juste mentionner que je commence à voir les tableaux comme de la peste. Surtout sur une structure ou tu ne peux pas gérer la taille du tableau.
Si le dossier contient 5 fichiers, ca va pas être méchant. En revanche, si ton dossier en possède des milliers/millions, tu risque d'avoir des problèmes de mémoire.

La spl te fournit une itération à la volée, pourquoi ne pas en profiter ?
Pourquoi parcourir (boucler) le dossier pour mettre le contenu dans un tableau, et ensuite re-boucler sur ce tableau pour afficher le contenu ?

Si, en tant que moteur de template, tu utilise php (ce que je fait, car à l'origine, php à été réalisé pour faire office de moteur de template, ndlr), tu peux passer un objet qui implémente iterator et qui parcours le dossier.

Par exemple tu peux instancier tout ton système est passer ton objet à ton moteur de template. Ou si tu veux rajouter des restrictions, tu peux faire une classe spécifique pour ton moteur de template, et passer un objet iterator (__construct (iterator $oTonObjet)) afin que quand tu boucle sur la classe spécifique, celle ci bouclera sur l'objet donné dans le constructeur.
Ca à l'avantage d'être générique (itérateur pour un dossier, pour un contenu de fichier (par lignes), contenu d'une base de donnée, etc, etc, etc).

En tout cas très bon travail. L'intérêt que tu montre à la SPL montre tout simplement que tu te tiens à jour (la SPL n'est là que depuis PHP 5.2), et que tu ne nous ponds pas des classes en php 4 :p
Messages postés
39
Date d'inscription
vendredi 9 mai 2003
Statut
Membre
Dernière intervention
25 mai 2009

Salut les boss ! Je vois que ça réagit, ça fait plaisir. Bon, si ça peut vous faire désenfler, j'aurais pû ajouter à la liste des gourous Coucou747 ou Codefalse par exemple mais je vais m'arrêter là sous peine de faire des jaloux ! ;) Je ne sais pas si le terme de gourou vous convient mais en ce qui me concerne, je suis autodidacte, formé par vos soins sur ce site, à l'insu de votre plain gré. Vos interventions toujours bien avisées transforment les classes basiques en de véritables mines d'informations (sur ce qu'il ne faut pas faire en général, ou sur comment mieux faire)
Pour mon pseudo, désolé mais Malalam était déjà pris ... j'ai fait avec ce qu'il restait ! ;-)

Bon, pour en revenir à la source, je vois que vous avez un peu de mal tous les 2 avec la partie arborescence en HTML. C'est vrai que côté MVC, l'idéal serait de sortir cette fonction ; en tout cas, comme ça, ça a le mérite de ne pas avoir à passer par x classes externes pour sortir l'info qui peut être gérée ici. Je dois bien dire que 'dans la vraie vie', j'utilise une classe pour gérer les arborescences graphiques. Je lui transmets un Array organisé spécialement pour ça et il en ressort une arbo HTML. Mais tout ça est un petit peu lourd à placer ici (et j'ai pas non plus envie d'y mettre toutes mes sources ;-) Avec ce que je propose ici, c'est déjà presque un micro moteur de template puisque je génère des variables qui vont pouvoir être insérées dans les <li> (qu'on peut d'ailleurs remplacer par des
, , ...)
Par contre, ta proposition de gérer ça avec la SPL m'intéresse. Il faudrait que je regarde ça de plus prêt. En fait j'utilise pas mal de classes perso dont je me rend compte qu'elles sont déjà développées par la SPL. J'ai notamment développé une class que j'ai appellée 'gestion des hierarchies' et qui ne fait rien d'autre que ce que font les classes Iterator (sauf qu'Iterator est plus complet !)

Bon, ma function actuelle de création de l'arborescence peut paraître un peu compliquée parceque j'essaie de gérer tous les cas. Genre on ouvre un pour un dossier et il faut ensuite le refermer avec un quand on a fini de lister le dossier puis fermer la ligne <li> qui contenait ce dossier avec </li>. Seulement, il ce peut qu'on ferme plusieurs dossiers à la suite. On va donc se retrouver avec une suite de </li></li></li>. Et c'est ça qui prend quelques lignes dans la fonction.
Le problème vient peut-être du fait que, merci la SPL, l'arborescence qui nous est livrée est ordonnée de façon parfaitement linéaire pour ce qu'on veut en faire. Les fichiers et les dossiers ne sont pas mêlangés, il suffit de parcourir l'objet avec un foreach et de suivre tout naturellement l'ordre donné. J'ai donc utilisé cette facilité mais peut-être faudrait-il prendre en compte un fonctionnement moins linéaire ? Mais dans ce cas, je ne vois pas vraiment comment faire ... ?!

Bon, j'arrête pour ce soir, il y a déjà de quoi lire ;) Merci pour vos commentaires, je vais voir ce que je peux en faire !
Messages postés
10840
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
23
Ah, juste: concernant ta méthode arborescence et la sortie...c'est bien, là-dessus que j'appuie : ta méthode est compliquée, à priori, parce que tu veux reproduire l'arbo dans une liste HTML. Avec une classe de sortie dédiée ET SPLisée, je pense que tu peux obtenir un truc beaucoup plus puissant, plus souple, ET alléger du même coup ta méthode arborescence (au détriment d'une nouvelle classe plus complexe hein...mais aussi plus puissante).
Vlà.
Afficher les 7 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.