Directorylistings mit PHP

Ziel dieses Artikels

In einen meiner vorherigen Artikel habe ich beschrieben, wie man Verzeichnislistings mit Hilfe des FancyIndexings des Apache Servers erstellen lassen kann muss man schon fast sagen, da ja der Apache den Code für das Listing erstellt. Wir haben festgestellt, dass dies eine sehr bequeme Art ist Inhaltsverzeichnisse ausgeben zu lassen. Man braucht einfach nur eine entsprechende Datei im selben oder übergeordneten Ordner und schon hat man ein entsprechendes DirectoryListing für den selber und/oder die Unterordner:

Doch leider ist man, was die Formatierung angeht, ziemlich eingeschränkt. Wählt man zum Beispiel für die pre-Tags im Stylesheet eine Schrift mit nicht gleich breiten Zeichen, so gerät das DirectoryListing doch etwas aus der Form. Das liegt einfach daran, dass wir es nicht mit einer formatierten Tabelle zu tun haben, sondern mit der Tatsache, dass der Apache einen vorformatierten Text mit pre-Tags ausliefert. Was, nebenbei bemerkt, noch dazu führt, dass es kein validates HTML ist, da innerhalb des pre-Tags mit dem Image-Tag gearbeitet wird.

In diesem Artikel will ich nun zeigen, wie man sich mit PHP ebenso bequem ein Verzeichnislisting erstellen lassen kann ohne nachher viel Arbeit zu haben. Ich setzte voraus, dass man sich schon mal grundlegend mit PHP beschäftigt hat.

Das Script

Das eigentliche Script liegt in einer PHP-Datei mit der Endung php. Dies Datei wird dann später in unsere Ausgabedatei eingebunden und die entsprechende(n) Funktion(en) daraus aufgerufen. Ich habe die Datei einfach dirhelpers.php genannt. Als nächstes brauchen wir eine Funktion, die uns eine Liste mit den Dateien in einem Verzeichnis zurückliefert. Diese könnte zum Beispiel so aussehen:

function ListFiles($dir, $SortOrder)
{
  $files=Array();
  $handle=opendir($dir);
  $count=0;

  while(false !== ($file = readdir($handle)))
  {
    if ($file != 'index.php' && $file[0] != '.' && $file != 'dir.php' && is_file($file))
    {
      $files[$count] = $file;
      $Time[$count]=filemtime($files[$count]);
      $Size[$count]=filesize($files[$count]); 
      $count++;
    }
  }
  closedir($handle);
  if ($SortOrder == 'name')
  {
    array_multisort($files, SORT_ASC, $files);
  }
  elseif ($SortOrder == 'time')
  {
    array_multisort($Time, SORT_DESC, $files);
  }
  elseif ($SortOrder == 'size')
  {
    array_multisort($Size, SORT_ASC, $files);
  }
  
  return $files;
}

Diese Funktion nimmt als Argumente das Verzeichnis, und als weiteren Parameter wie sortiert werden soll, entgegen und liefert ein Array mit dem im Verzeichnis gefundenen Dateien zurück. Hauptbestandteil dieser Funktion sind die PHP-Funktionen opendir [1] und readdir [2]. opendir gibt ein Verzeichnishandle zurück, welches wir dann für den Aufruf von readdir brauchen. readdir liest so lange Dateien aus dem Verzeichnis, wie Dateien vorhanden sind und liefert dann, wenn keine mehr gefunden werden, false zurück.

Wir rufen nun in der while-Schleife [3] so lange readdir auf, wie es true zurückgibt. Innerhalb dieser Schleife schreiben wir jede gefundene Datei dann in das Array $files. Damit wir auch jedes mal einen neuen Eintrag im Array erhalten, erhöhen wir nach jeder Datei den Index $count und geben ihn als Position an, wo wir die gefundene Datei im Array ablegen wollen.

Unsere Schleife weißt noch zwei Besonderheiten auf: 1. Haben wir eine if-Bedingung [4], die erstens dafür sorgt, dass Dateien mit dem Namen 'index.php', dem Punkt als erstes Zeichen ausgelassen werden und zweitens wirklich nur Dateien und keine Verzeichnisse in die Liste aufgenommen werden. Zweiteres geschieht mit der Funktion is_file [5], die prüft, ob es sich bei dem gefundenen Eintrag um eine Datei handelt oder nicht. 2. In der Schleife füllen wir desweiteren noch zwei weitere Arrays, nämlich einmal ein Array mit dem letzten Änderungsdatum und ein Array mit der Dateigröße. Diese Angaben benötigen wir dann noch, um das Array mit den Dateien dann entsprechend sortieren zu können.

Nach der Schleife wird dann nur noch das Verzeichnishandle geschlossen und, abhängig vom Sortier-Parameter, die Funktion array_multisort [6] aufgerufen, um das Array mit den Dateien entsprechend zu sortieren.

Das war eigentlich schon alles. Als nächstes gucken wir uns nun an, wie wir das ganze in eine Datei einbinden, die man mit dem Browser dann abrufen kann.

Einbinden des Scripts in eine Datei zur Ausgabe

Ich habe mich dafür entschieden eine normale HTML-Datei zu benutzen, in der ich PHP-Code inkludiere. Diese HTML-Datei ist eine ganz normale HTML-Datei vom Aufbau her, nur, dass sie die Endung php trägt. Am anschaulichsten wird das ganze, wenn ich den Code solch einer Datei einfach mal zeige:

<html>
<body>
  <p>
    Verzeichnislisting:
  </p>
  <table>
  <?php
    $dir = getcwd();
    $end = strpos(strtolower($dir), '/html/')+6;
    $s = substr($dir, 0, $end);
    include $s.'php/helpers.php';
  
    $files = ListFiles('.', $SortOrder);
      foreach($files as $file)
      {
        echo '<tr>';
        echo '<td class="dir"><a href="'.$file.'">'.$file.'</a></td>'.
          '<td class="dir">'.format_filesize(filesize($file)).'</td>'
          .'<td class="dir">'.date("Y-m-d H:i", filemtime($file)).'</td>';
        echo '</tr>';
      }
  ?>
  </table>
</body>
</html>

Als Ergebnis bekommen wir dann folgende Ausgabe:

Wichtig sind hier drei Zeilen. Die Zeile, in der Die Datei mit dem Script eingebunden wird: include [7], die Zeile mit dem Aufruf der Funktion: $files = ListFiles('.', $SortOrder); und die Schleife, die die Zeilen der Tabelle erzeugt: foreach [8]. Diese Datei wird dann einfach in das Verzeichnis hochgeladen, für das wir das Verzeichnislisting haben wollen, und den Rest erledigt unser Script.

Mit etwas mehr Aufwand und ein paar zusätzlichen Funktionen könnte es dann aber auch so aussehen:

Die zusätzlichen Funktionen, die man unter anderem braucht, und dem in diesem Artikel besprochenen Code, finden sich in der Datei dirhelpers.txt [9].

Ergänzt: 2006-01-15:
Und noch die Datei, in der das Verzeichnislisting dann eigentlich erzeugt wird: dirindex.txt [10]. Aufgerufen wird das Script zum Beispiel so:

http://www.michael-puff.de/dirindex.php?folder=Developer/Artikel/&SortOrder=time
Wobei der Pfad immer mit einem Slash "/" abgeschlossen werden muss, damit die Links in das Verzeichnis eine Ebene höher richtig funktionieren.

2010-12-29T23:44:42 +0100, mail+homepage[at]michael-puff.de