Phar Tutorial – PHP Archive
Da ich mich heute endlich mal mit einem neuen Feature aus PHP 5.3 beschäftigen konnte, will ich meine Erkenntnisse Niemanden vorenthalten. Das neue Features nennt sich Phar und ich bin mir sicher, dass wir davon noch viel Zukunft hören werden. Jetzt gibt es aber erstmal eine kleine Einführung.
Phar ist eine Zusammenführung der beiden Wörter PHP und Archiv und ähnelt dem .jar-Format von Java (jar = Java Archiv). In einem Phar-Archiv können prinzipiell alle Datei-Fromate verpackt werden und so lassen sich beispielsweise komplette PHP-Anwendungen in eine Datei archivieren, damit sie leichter verbreitet werden kann.
Ein neues Archiv lässt sich mit den folgenden Code-Zeilen anlegen:
$dir = __DIR__.'/'; $archive = new Phar($dir.'myphar.phar.gz'); |
Wir legen also ein neues Archiv mit dem Namen myphar.phar.gz an, das Gzip komprimiert ist (zu erkennen an der Endung .gz).
Die Phar-Klasse steht natürlich nur dann zur Verfügung, wenn die Extension auch in der php.ini aktiviert wurde.
Als nächstes müssen wir dem Archiv noch Daten zuführen. Dazu legen wir ein neues Verzeichnis test an mit einer Datei hello.php und dem Inhalt
echo 'hello world'; |
Jetzt können wir folgenden Befehl verwenden, um alle Daten aus dem Test-Verzeichnis in das Archiv zu speichern:
$archive->buildFromDirectory($dir.'test'); $archive->stopBuffering(); |
Mit der Methode stopBuffering() werden die Daten dann auf die Festplatte geschrieben.
Wir brauchen also nur knapp 4 Zeilen Code um ein ganzes Archiv anzulegen, aber wie bekommt man die Dateien jetzt wieder raus? Dazu gibt es mehrere Möglichkeiten. Welche man benutzt, hängt davon ab was man mit dem Inhalt machen möchte. Zunächst öffnen wir das Phar-Archiv aber erstmal:
$dir = __DIR__.'/'; $archive = new Phar($dir.'myphar.phar.gz'); |
Jetzt können entweder den ganzen Inhalt zur Laufzeit auslesen, oder aber wieder in ein normales Verzeichnis entpacken.
// Alle Dateien auslesen foreach($archive as $file) { $ext = strrchr($file->getBasename(), '.'); // PHP-Dateien können per include einfach eingebunden werden. if($ext == '.php') { include $file->getPathname(); } } // Alle Dateien in ein normales Verzeichnis entpacken $archive->extractTo($dir.'myphar'); |
Wenn man genau weiß welche PHP-Datei man haben will, kann man diese auch direkt inkludieren, ohne das Archiv zu öffnen. Dazu muss man nur ein “phar://” vor den Pfad stellen:
$dir = __DIR__.'/'; include 'phar://'.$dir.'myphar.phar.gz/hellp.php'; |
So, das sind erstmal die Grundfunktionen, die man von Phar Wissen sollte. Aber man merkt schnell, dass Phar ziemlich einfach zu handhaben ist, weil alles schön in Klassen verpackt ist.
Und noch ein letzter Tipp: Phar baut zum größten Teil auf die SPL Klassen SplFileInfo und DirectoryIterator. Die sollte man sich daher mal genauer anschauen.
SPL: DirectoryIterator und SplFileInfo
Heute geht es um die Standard PHP Library, kurz SPL. Oder genauer gesagt um die Klassen DirectoryIterator und SplFileInfo. Vorab aber erstmal ein paar Infos zur SPL.
Die SPL ist eine Art Framework für PHP. Es besteht aber noch ein großer Unterschied zu normalen Frameworks, wie das Zend Framework, CodeInteger und Co, denn die SPL liegt in kompilierter Form vor. Das macht die Bibliothek nicht nur schneller, sondern bietet auch viel mehr Möglichkeiten. Die SPL ist nämlich genau wie die Sprache PHP selbst in C geschrieben. So kann man zum Beispiel mit SPL-Interfaces den eigenen Klassen ganz neue Funktionalitäten hinzufügen, die man mit Standard-Funktionen gar nicht erreichen kann. Über die SPL-Interfaces werde ich demnächst auch nochmal berichten – ist nämlich auch ein ziemlich interessantes Thema. Jetzt aber zum DirectoryIterator und der SplFileInfo.
Wenn man mit PHP Standard-Mitteln ein Verzeichnis ausgeben wollte, würde das ungefähr so aussehen:
function showDirectoryListing($path) { $basename = basename($path); $handle = opendir($path); echo '<ul>'; while($file = readdir($handle)) { if($file != '.' && $file != '..') { if(is_dir($basename.$file)) { echo '<li class="directory">'.$file.'</li>'; } else { echo '<li class="file">'.$file.'</li>'; } } } closedir($handle); echo '</ul>'; } |
Besonders schön ist diese Lösung nicht, aber jetzt kommt die Klasse DirectoyIterator ins Spiel. Mit dieser Klassen können wir Verzeichnisse viel komfortabler Auslesen, denn wir bekommen jeden Eintrag als Objekt der Klasse SplFileInfo zum verarbeiten. Die SplFileInfo-Klasse stellt viele Methoden zur Verfügung, um Dateien und Verzeichnisse besser bearbeiten zu können. Hier nochmal die Überarbeitete Fassung der obigen Funktion:
function showDirectoryListing($path) { echo '<ul>'; $handle = new DirectoryIterator($path); foreach($handle as $file) { if(!$file->isDot()) { if($file->isDir()) { echo '<li class="directory">'.$file->getFilename().'</li>'; } else { echo '<li class="file">'.$file->getFilename().'</li>'; } } } echo '</ul>'; } |
Diese Variante sieht doch schon um einiges sauberer aus. Einen richtigen Unterschied wird man aber erst dann richtig bemerken, wenn man noch mehr mit den Dateien arbeiten muss (z.B. wenn es darum geht noch weitere Informationen zu den Dateien auszugeben).
Insgesamt helfen diese zwei Klassen also den Code sauberer und komfortabler zu gestalten. Außerdem wird dadurch endlich der Zugriff auf Verzeichnisse und Dateien mit eine performanten Lösung standardisiert. Wenn ihr also das nächste Mal auf ein Verzeichnis zugreifen müsst, solltet ihr diesen Weg nutzen.
Und noch ein kleiner Tipp: SPL-Klassen lassen sich ohne Weiteres erweitern und so könnt ihr problemlos eine eigene, verbesserte FileInfo-Klasse schreiben (falls ihr so was braucht).