Aller au menu Aller au contenu Plan du site accessibilité

P0de*fr

Introduction

Dans certains cas l'utilisation de fichiers est plus appropriée que l'utilisation d'une base de données, c'est pourquoi j'aborderai dans ce tutorial les fonctions les plus utilisées dans la manipulation de dossiers et fichiers.

Voici les différents points abordés :

Applications possibles :

1. créer un dossier - up

Commençons simplement, avec la création d'un dossier.

<?php
mkdir ("/chemin_du_dossier/nom_du_dossier", 0700);
?>

Le 0700 correspond au mod, il est en base octale. Le mode correspond aux droits en RWX accordés au dossier, ceci ne fonctionne pas sous windows, et est optionnel depuis PHP 4.2.0. Par défaut le mode est 0777 ce qui correspond aux maximum de droits.

Pour supprimer un dossier il faut utiliser la syntaxe suivante :

<?
rmdir ("/chemin_du_dossier/nom_du_dossier");
?>

Il faut cependant que le script dispose des droits suffisants et que le dossier soit vide.

Une fois exécutées, ces deux fonctions renvoient TRUE ou FALSE selon qu'elle ait fonctioné ou pas. On peut donc tester si un répertoire a bien été créé :

<?
if (mkdir ("/chemin_du_dossier/nom_du_dossier")) {
echo "Création du répertoire OK";
} else {
echo "Echec de la création";
}
?>

2. scanner le contenu d'un dossier - up

Il existe en PHP des fonctions permettant de visualiser le contenu d'un répertoire et d'obtenir diverses informations sur les fichiers qu'on y trouve. Pour commencer, on va ouvrir un dossier, puis scanner son contenu.

<?php
$handle = @opendir("."); //Ouverture du répertoire et récupération du pointeur
while ($file = @readdir($handle)) { //On scanne le répertoire
echo $file."<?br /?>"; //On affiche le nom du fichier lu à chaque boucle
}
@closedir($handle);
?>

Il peut arriver qu'un répertoire que l'on cherche à ouvrir n'existe pas, dans ce cas là opendir retournerait une erreur. le "@" devant la fonction précise que si erreur il y a, le script ne doit pas l'afficher dans la page généré. cette astuce est valable pour toute fonction.
la fonction opendir demande en argument une chaîne de caractère, le "." est le répertoire courant, on aurait pu mettre "/" pour la racine, ".." pour le répertoire parent, ou n'importe quel autre dossier...
pour fonctionner, readdir demande le pointeur d'un dossier, et non son nom, dans ce script $handle contient ce pointeur. si vous êtes curieux vous pouvez faire un echo $handle; pour voir sa valeur.
lorsque readdir a parcouru tous les fichiers du répertoire, la fonction renvoie false, ce qui a pour effet de mettre fin à la boucle. après ça il faut fermer le répertoire avec closedir.

bien sûr il est possible d'obtenir d'autres informations sur les fichiers lu que leur nom. on peut aussi obtenir leur taille, date de modification, les droits attribués...

<?php
filesize($file); //taille du fichier;
filemtime($file); //date de dernière modification;
filetype($file); //type du fichier : file, dir, fifo, char, link, block, unknown
?>

Il est possible d'obtenir d'autres informations mais elles sont moins utiles, reportez-vous à la documentation php pour en savoir plus. pour savoir si le fichier scanné est un dossier il existe une autre fonction :

<?php
is_dir($file);
?>

Cette fonction renvoie true ou false selon que $file soit un fichier ou un dossier. il existe une fonction is_file() dont vous aurez compris l'utilité. si on désire savoir si l'objet scanné est un fichier ou un dossier on a donc deux solutions :

<?php

//solution 1

$handle = @opendir(".");
while ($file = @readdir($handle)) {
if (@filetype($file) == "dir") { echo $file." est un dossier <br />"; } //$file est un dossier?
}
@closedir($handle);

//solution 2

$handle = @opendir(".");
while ($file = @readdir($handle)) {
if (is_dir($file)) { echo $file." est un dossier <br />"; } //$file est un dossier?
}
@closedir($handle);
?>

le répertoire courant correspond au répertoire dans lequel se trouve le fichier php qui est exécuté. si on désire obtenir le répertoire courant on peut utiliser la fonction getcwd().

<?php
echo getcwd(); //retourne le chemin et le nom du répertoire courant
?>

pour changer de répertoire courant il faut utiliser la fonction chdir. ceci peut être utile par exemple lorsqu'on manipule des fichiers se trouvant dans un autre répertoire que celui du script, il n'est alors plus utile de préciser le chemin complet de chaque fichier pour chaque fonction puisque les fichiers appelés seront considérés comme étant dans ce répertoire.

<?php
echo getcwd()."<br />"; //retourne le chemin et le nom du répertoire courant
@mkdir("new_dir", 0700); //on créé un nouveau répertoire appelé new_dir
echo getcwd()."<br />"; //on affiche le répertoire courant, il n'a pas changé.
@chdir("new_dir"); //on change de répertoire courant
echo getcwd()."<br />"; //on affiche le répertoire courant, c'est maintenant new_dir
?>

3. lire le contenu d'un fichier - up

on va maintenant voir comment récupérer des informations dans un fichier texte se trouvant sur le server. soit le fichier suivant : fichier_exemple.txt

fichier_exemple.txt

[titre]fichier exemple[/titre]
[auteur]olivier scherrer[/auteur]
[date]30/11/2003[/date]
[texte]la loutre est un mammifère carnivore qui appartient à la famille des mustélidés comme la fouine,
la martre, le vison, le putois, le blaireau, la belette ou l'hermine. en france, on ne trouve qu'une
seule espèce de loutre, la loutre d'europe (lutra lutra ). même si elle possède de nombreux points
communs avec les autres mustélidés, sa biologie présente des caractéristiques bien particulières.[/texte]

On veut l'ouvrir et récupérer les différentes informations, titre, auteur, date, texte.

lecture.php

<?php
$fp = @fopen("fichier_exemple.txt", "r"); //ouverture du fichier en readonly
if ($fp) { //si le fichier existe et qu'on a bien réussis à l'ouvrir
while (!feof ($fp)) { //lecture ligne par ligne jusqu'à fin du fichier
$line = fgets($fp); //on stock la ligne courante dans $line
eregi("\[titre\](.*)\[\/titre\]", $line, $titre);
eregi("\[auteur\](.*)\[\/auteur\]", $line, $auteur);
eregi("\[date\](.*)\[\/date\]", $line, $date);
eregi("\[texte\](.*)\[\/texte\]", $line, $texte);
}
fclose($fp);
}
echo $titre[1]."<br />".$auteur[1]."<br />".$date."<br />".$texte[1]."<br />"; //affiche le résultat
?>

Les balises ont été choisies arbitrairement, on aurait très bien pu mettre auteur-olivier scherrer, /auteur\ olivier scherrer, 4ut3u7~olivier scherrer, etc. le tout est de changer ensuite l'expression régulière.

Epluchons ce script. <br />
Tout d'abord on ouvre le fichier dont on veut lire le contenu. il faut mettre son chemin d'accès et son nom en premier paramêtre, puis son attribut pour l'ouverture :

 'r'- ouvre en lecture seule, et place le pointeur de fichier au début du fichier.

 'r+' - ouvre en lecture et écriture, et place le pointeur de fichier au début du fichier.

 'w' - ouvre en écriture seule; place le pointeur de fichier au début du fichier et réduit la taille du fichier à 0. si le fichier n'existe pas, on tente de le créer.

 'w+' - ouvre en lecture et écriture; place le pointeur de fichier au début du fichier et réduit la taille du fichier à 0. si le fichier n'existe pas, on tente de le créer.

 'a' - ouvre en écriture seule; place le pointeur de fichier à la fin du fichier file. si le fichier n'existe pas, on tente de le créer.

 'a+' - ouvre en lecture et écriture; place le pointeur de fichier à la fin du fichier. si le fichier n'existe pas, on tente de le créer.

(les attributs sont extrait de la doc php)

Une fois que ce fichier est ouvert, on va lire son contenu ligne par ligne tant qu'on n'atteind pas la fin du fichier. ceci est effectué par la boucle while (!feof ($fp)) {.... comme on l'a vu précédement, $fp contient le pointeur du répertoire ouvert avec fopen. maintenant il faut stocker le contenu de chaque ligne lue dans une variable, qu'on va appeler $line par exemple. la fonction fgets permet d'enregistrer ce texte.
enfin, la fonction eregi va vérifier si les balises spécifiées existent, et récupérer, si c'est le cas, le texte qu'elles contiennent. on peut alors l'afficher. enfin, il faut fermer le fichier avec fclose.

4. placer du contenu dans un fichier - up

voyons maintenant comment placer du contenu dans un fichier. ce fichier peut être vide ou contenir déjà des informations. lors de l'ouverture du fichier à manipuler, il faudra bien préciser l'attribut approprié (voir la section précédente pour l'explication des attributs).

on va essayer de créer un nouveau fichier, de récupérer le contenu de fichier_exemple.txt et le copier en changeant les balises.

copy.php

<?php

//on commence par récupérer les informations de fichier_exemple.txt

$fp = @fopen("fichier_exemple.txt", "r"); //ouverture du fichier en readonly
if ($fp) { //si le fichier existe et qu'on a bien réussis à l'ouvrir
while (!feof ($fp)) { //lecture ligne par ligne jusqu'à fin du fichier
$line = fgets($fp); //on stock la ligne courante dans $line
eregi("\[titre\](.*)\[\/titre\]", $line, $titre);
eregi("\[auteur\](.*)\[\/auteur\]", $line, $auteur);
eregi("\[date\](.*)\[\/date\]", $line, $date);
eregi("\[texte\](.*)\[\/texte\]", $line, $texte);
}
fclose($fp);
}

//puis on génère la chaine de caractère à copier dans le nouveau fichier

$text = "<titre>".$titre[1]."</titre>\n";
$text .= "<auteur>".$auteur[1]."</auteur>\n";
$text .= "<date>".$date[1]."</date>\n";
$text .= "<texte>".$texte[1]."</texte>\n";

//on la place dans le nouveau fichier, il faut d'abord l'ouvrir.

$fichier = fopen("nouveau_fichier.txt","w"); //(si il n'existe pas fopen le crée)
fputs($fichier,$text); //copie du texte dans le fichier
fclose($fichier); //on ferme le fichier
copy($fichier); //ecriture du fichier sur le server
?>

il est aussi possible de copier, renommer et supprimer des fichiers.

<?php
copy("fichier_exemple.txt","copie_de_fichier_exemple.txt");
rename("copie_de_fichier_exemple.txt"); //renommage
unlink("copie_de_fichier_exemple.txt"); //suppression
?>

C'en est maintenant fini de la partie théorique, voyons à présent deux applications de ce que nous venons de voir.

application : explorateur de dossiers - up

Ce script très simple tient dans un fichier .php. il va lister le contenu d'un répertoire précisant diverses informations sur le fichiers qu'on y trouve. un champs texte permet de spécifier le répertoire que l'on veut scanner. ce script permet d'afficher le contenu des fichiers listés si ce sont des fichiers textes, images ou html, sinon il proposera de les télécharger. les fichiers .php par exemple ne sont donc pas exécutés.
illustration de l'application

contenu_dossier.php

<!doctype html public "-//w3c//dtd html 4.01 transitional//en">
<html>
<head>
<title>explorateur de dossiers</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<style type="text/css">
<!--
td,body {
margin: 20px;
background-color: #eeeeee;
font-family: verdana;
font-size: 10pt;
color: #000000;
}
.dir
{
text-decoration:underline;
color: #0000ff
}
.dir:hover
{
text-decoration:underline;
}
.file
{
text-decoration:none;
color: #ff0000
}
.file:hover
{
color:#000000;
}
-->
</style>
</head>
<body>
<form method="get" action="<?=$php_self?>">
<input type="text" name="dossier">
<input type="submit" value="listage">
</form>
<?php

$perms[33206] = "rw";
$perms[33060] = "r only";
$perms[16895] = "dossier classique";
$perms[33279] = "fichier systeme";
$perms[16749] = "dossier systeme";
$perms[33133] = "truc bizzare encore";

$dossier = $_get['dossier'] ? $_get['dossier'] : "."; //dossier courant par défaut
$dir = htmlspecialchars($dossier);

if (!@chdir($dir)) { die("ouverture impossible"); }
$handle = @opendir($dir);
$repcourant = getcwd(); //stocke l'adresse du dossier courant pour créer les liens
echo "<b>contenu du dossier suivant : [ ".getcwd()." ]</b><br><br>\n";
echo "<table width=100% border=1 bordercolor=#000000 cellspacing=0 cellpadding=5>";

echo "<tr><td><b>nom</b></td><td><b>taille</b></td>
<td><b>type</b></td><td><b>date dernière modif</b></td><td><b>permissions</b></td></tr>\n";
while ($file = @readdir($handle)) {

$ligne = "<tr>";

//nom du fichier ou dossier
if (@filetype($file) == "dir") {
$ligne .= "<td><a href=\"contenu_dossier.php?dossier=".$repcourant."/".$file."\"
class=".@filetype($file).">".$file."</a></td>";
} else {
$ligne .= "<td><a href=\"".@realpath($file)."\" class=".@filetype($file).">".$file."</a></td>";
}

//taille du fichier
$sizeoffile = @filesize($file);
$ligne .= "<td>".$sizeoffile." octets</td>";

//type (dossier ou fichier)
$typeoffile = @filetype($file);
$ligne .= "<td>".$typeoffile."</td>";

//dernière modif
$lastfilemodif = @filemtime($file);
$ligne .= "<td>".@date("d/m/y",$lastfilemodif)."</td>";

//permissions du fichier
$permsoffile = @fileperms($file);
$ligne .= "<td>".$perms[$permsoffile]."</td>\n"; // affichage texte des permissions
//$ligne .="<td>".$permsoffile."</td>\n"; // affichage des permissions

$ligne .="</tr>";
echo $ligne;

}
@closedir($handle);

?>

</table>
</body>
</html>

application : mini galerie - up

Cette galerie php va récupérer des informations dans des fichiers textes. un premier menu sera généré, listant les différents fichiers dont le contenu est accessible. ensuite, on sélectionne un de ces fichiers, et le script ira récupérer les informations et affichera l'image associée. dans ce script sont abordés les points : parcourt d'un répertoire, ouverture d'un fichier, lecture de son contenu.

Voici le résultat produit par ce script :
illustration de la galerie

mini_galerie.php

<!doctype html public "-//w3c//dtd html 4.01 transitional//en">
<html>
<head>
<title>mini galerie php</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<style type="text/css">
<!--
td,body {
margin: 20px;
font-family: verdana;
font-size: 10pt;
color: #000000;
}
.link {
text-decoration:none;
color: #333333;
}
.link:hover {
text-decoration:underline;
}
-->
</style>
</head>
<body bgcolor="#eeeeee">
<table width="700" cellspacing="0" border="0" align="center">
<tr>
<td width="150" valign="top">
<!-- menu -->

<table width="100%" cellspacing="1" bgcolor="#000000" border="0" cellpadding="5">
<tr>
<td bgcolor="#cccccc" align="center">
<b>sites</b>
</td>
</tr>
<?php

//génération de la liste de liens

$handle = @opendir("fichiers_galerie"); //on ouvre le répertoire
while ($file = @readdir($handle)) { //on le parcourt
$ext = explode(".", $file); //on explode le fichier lu

if ($ext[1] == "txt") { //a t'il l'extension txt?

$fp = @fopen("fichiers_galerie/".$file,"r"); //si oui on l'ouvre

if ($fp) {

while (!feof ($fp)) { //tant que l'on n'atteind pas la fin du fichier
$line = fgets($fp, 1024);

eregi ("\[titre\](.*)\[\/titre\]", $line, $nom); //on récupère le titre

}
}

echo "<tr>\n"; //on peut générer une nouvelle ligne avec le fichier en lien
echo " <td align=\"center\" bgcolor=\"#ffffff\">\n";
echo "<a href=\"mini_galerie.php?url=".$file."\" class=\"link\">".$nom[1]."</a>\n";
echo " </td>\n";
echo "</tr>\n";
}
}
@closedir($handle);

?>
</table>

</td>
<td width="550" valign="top">
<!-- contenu -->

<table width="100%" cellspacing="1" border="0" bgcolor="#000000" cellpadding="5">

<?php

$url = $_get['url'] ? $_get['url'] : 'hfr.txt'; //si on n'a choisi aucun lien on prend hfr.txt par défaut
$url = addslashes(htmlentities($url)); //sécurisation
$ext = explode(".", $url); //on revérifie que ce soit bien un fichier txt
if ($ext[1] == "txt") {

$fp = @fopen("fichiers_galerie/".$url,"r");

if ($fp) {

while (!feof ($fp)) { //tant que l'on n'atteind pas la fin du fichier

$line = fgets($fp, 1024);

eregi ("\[titre\](.*)\[\/titre\]", $line, $titre); //on récupère le contenu
eregi ("\[legende\](.*)\[\/legende\]", $line, $leg); //de chaque balise
eregi ("\[url\](.*)\[\/url\]", $line, $url);
eregi ("\[description\](.*)\[\/description\]", $line, $desc);
eregi ("\[img\](.*)\[\/img\]", $line, $img);
}
}
}

@closedir($handle); //on ferme le répertoire

echo "<tr>\n"; //on affiche les informations
echo " <td bgcolor=\"#cccccc\" align=\"center\">\n";
echo " <b>".$titre[1]."</b>\n";
echo " </td>\n";
echo "</tr>\n";
echo "<tr>\n";
echo " <td bgcolor=\"#ffffff\" align=\"center\">\n";
echo "<b>".$leg[1]."</b><br><br>\n";
echo " <img src=\"fichiers_galerie/".$img[1]."\" alt=\"".$titre[1]."\"><br><br>\n";
echo " <b><a href=\"".$url[1]."\" class=\"link\" target=\"_blank\">".$url[1]."</a></b><br><br>\n";
echo $desc[1]."\n"; echo " </td>\n";
echo "</tr>\n";

?>
</table>

</td>
</tr>
</table>
</body>
</html>