Ergebnis 1 bis 12 von 12

Thema: PHP 5 für Fortgeschrittene - Die Standard PHP Library

  1. #1
    TP-Specialist Avatar von phpBuddy
    Registriert seit
    Aug 2004
    Ort
    Kaiserslautern
    Beiträge
    4.678

    PHP 5 für Fortgeschrittene - Die Standard PHP Library

    Vorwort

    Mit PHP 5, das mittlerweile bereits 3 Jahre alt ist, haben auch viele neue Funktionen Einzug in den Programmierer Alltag gehalten. Einige der neuen Funktionen haben auf Anhieb den Weg in's Programmierer Herz gefunden, während andere Neuerungen nach wie vor unbeachtet bleiben.
    Eine dieser genialen, aber wenig beachteten Neuerungen ist die Standard PHP Library kurz SPL. Mit wenigen Worten zu beschreiben was die SPL ist, ist nicht einfach. Prinzipiell versucht die SPL, wie es der Name schon vermuten läßt, für gewisse wiederkehrende Probleme einen einheitlichen Lösungs-Standard zu schaffen.
    Der Entwickler der SPL beschreibt es auf seiner Seite so:
    SPL - Standard PHP Library SPL is a collection of interfaces and classes that are meant to solve standard problems and implements some efficient data access interfaces and classes.
    In dieser SPL-Einführung wollen wir als Anschauungsobjekt eine relativ primitive Kernfunktion eines Datei-Backup Scripts erstellen das Verzeichnisse rekursive ausliest, bestimmte Datei-Typen herausfiltert und dann, unter Beibehaltung der Verzeichnisstruktur, ein Zip-Archiv der Dateien erstellt. Bei dieser Aufgabe lassen wir uns von den Iterator-Klassen der SPL helfen. Das hört sich im ersten Moment vielleicht schwierig und kompliziert an, aber wie wir sehen werden ist das, dank der SPL, (fast) so einfach wie eine Email per PHP zu versenden!

    Doch bevor wir anfangen sollte sich jeder der noch keine Ahnung hat was die SPL ist einen ersten Überblick verschaffen:
    Standard PHP Library Homepage

    Sollte man nach diesem Artikel auf den Geschmack gekommen sein, so sollte dieser Link in die Bookmarks aufgenommen werden. Leider ist die SPL (noch) sehr schlecht dokumentiert auf der PHP-Webseite und vieles findet man nur durch trial&error heraus. Die Übersicht auf der Entwicklerseite bietet noch den besten Überblick was mit der SPL möglich ist.



    Voraussetzungen

    Dieses Einführung richtet sich an fortgeschrittene PHP Programmierer. Dementsprechend sollten folgende Voraussetzungen erfüllt sein um diesem Artikel folgen zu können:
    • fundierte PHP Kenntnisse
    • ein gutes Verständnis der OOP
    • Webserver oder Xampp mit PHP 5 - optimalerweise das aktuelle PHP 5.2.3
    • aktivierte SPL und ZipArchive Klasse (sollte standardmäßig aktiv sein)


    Um zu prüfen ob die benötigten Klassen zur Verfügung stehen einfach eine PHP Datei mit dem Inhalt
    PHP-Code:
    echo "<pre>" .print_rget_declared_classes(), true ). "</pre>"
    auf dem Server aufrufen und schauen ob folgende Klassen-Namen aufgeführt sind.
    1. ArrayObject
    2. ArrayIterator
    3. RecursiveDirectoryIterator
    4. RecursiveIteratorIterator
    5. FilterIterator
    6. ZipArchive


    Sind alle Voraussetzungen erfüllt kann es los gehen. Die Erklärungen in dieser Einleitung fallen etwas knapper aus, als es in meinen anderen Tutorials der Fall ist. Grund dafür ist, daß der Artikel auch ohne detaillierte Erläuterungen recht lang ist und darüber hinaus ist der Stoff nicht schwer zu verstehen, wenn man die oben erwähnten Voraussetzungen mitbringt.



    Was ist ein Iterator?

    Der Ausdruck Iterator ist jetzt schon häufiger gefallen, deswegen sollten wir vielleicht erst einmal klären was ein Iterator überhaupt ist. Am besten trifft wohl die Bezeichnung Zeiger als Übersetzung zu. Wenn wir uns durch ein Objekt bewegen (iterate), verschieben wir dabei einen Zeiger (Iterator) innerhalb des Objekts um auf bestimmte Inhalte zuzugreifen. Dabei ist es uns egal wie die Struktur der Daten aussieht, alles was uns interessiert ist deren Inhalt. In allen untenstehenden Beispielen werde ich den Ausdruck Zeiger verwenden, damit man die Funktionsweise des Iterator besser nachvollziehen kann.



    Unser erstes Iterator-Beispiel

    Das klassische Anwendungsgebiet für Iteratoren sind Arrays. Also erstellen wir ein kleines Array, leiten ein Objekt davon ab und schauen uns an was wir damit anstellen können.
    PHP-Code:
    $webtechnologien = array( "PHP""HTML""CSS""MySQL""Ruby""JavaScript""Flash" );
    $objekt = new ArrayObject$webtechnologien );
    $zeiger $objekt->getIterator(); 
    Unser Array habe ich jetzt mal webtechnologien genannt, unabhängig davon ob jemand mit dem Inhalt des Array nicht einverstanden ist.
    In Zeile 2 sprechen wir bereits die Klasse ArrayObject an und übergeben unser Array an diese Klasse. Das zurück gelieferte Objekt legen wir in $objekt ab. Die Klasse ArrayObject stellt zahlreiche Methoden zur Verfügung, die uns den Umgang mit einem Array erleichtert. So kann man z.B. auf zahlreiche klassische Sortier-Funktionen zugreifen, wie etwa
    • $objekt->asort()
    • $objekt->ksort()
    • $objekt->uasort()
    • $objekt->uksort()
    • $objekt->natsort()
    • $objekt->natcasesort()

    Eine weitere Methode die man häufig braucht ist $objekt->count(), die einem die Anzahl der im Array befindlichen Elemente liefert. Benötigt wird das u.a. um zu wissen wie viele Schleifen-Durchläufe wir machen müssen, wie wir weiter unten noch sehen werden.
    Zusammen mit der Klasse ArrayObject werden automatisch weitere Klassen geladen die ihrerseits Methoden zur Verfügung stellt. Eine dieser Klassen ist die Iterator Klasse und bildet mit ihren Methoden den Kern des Ganzen. Wer sich mal "kurz" einen kleinen Überblick verschaffen möchte in welchem Zusammenhang die Iterator Klasse zu den anderen Klassen steht, dem möchte ich dieses niedliche Diagramm an's Herz legen.

    Aber schauen wir uns mal die Methoden der Iterator Klasse an:
    • current() - Beinhaltet den Wert des aktuellen Elements auf dem sich der Zeiger befindet
    • key() - Beinhaltet den Schlüssel des aktuellen Elements auf dem sich der Zeiger befindet
    • next() - Bewegt den Zeiger zum nächsten Element
    • rewind() - Bewegt den Zeiger an den Anfang des Objekts/Arrays
    • valid() - Prüft ob ein Element existiert, nachdem mit next() oder rewind() die Zeigerposition verändert wurde.

    In unserem Beispiel oben ermitteln wir also mit $zeiger = $objekt->getIterator(); die Position des aktuellen Elements und übergeben diese an unseren Zeiger. Ab sofort stellt unser Zeiger ($zeiger) ein Objekt dar und wir können mit den Methoden der Klassen ArrayObject und Iterator arbeiten. Machen wir das doch einfach mal, um das etwas zu verdeutlichen:

    PHP-Code:
    $webtechnologien = array( "PHP""HTML""CSS""MySQL""Ruby""JavaScript""Flash" );
    $objekt = new ArrayObject$webtechnologien );
    $zeiger $objekt->getIterator();

    $zeiger->rewind(); // setzt den Zeiger an die erste Position im Array
    echo $zeiger->count(). "<br>"// gibt 7 aus, da 7 Elemente in unserem Array sind
    echo $zeiger->current(). "<br>"// gibt PHP aus, da sich der Zeiger auf dem ersten Element befindet
    $zeiger->next(); // bewegt den Zeiger zur nächsten Position
    if ($zeiger->valid()) // prüft ob sich der Zeiger auf einem gueltigen Element befindet.
    {
        echo 
    $zeiger->key(). "<br>"// gibt 1 aus, da sich der Zeiger auf dem 2. Element befindet 

    Soweit mal die absoluten Basics. Jeder mit etwas PHP Erfahrung wird hier nicht wirklich etwas neues gesehen haben, abgesehen davon das wir ein Array objektorientiert angesprochen haben. Einzig rewind() ist vielleicht etwas neu, aber die Funktionsweise entspricht der von reset(), die hinlänglich bekannt sein sollte.


    Array Iteration in der Praxis
    Ist ja alles schön und gut, nur wühlt sich niemand manuell durch ein Array, deswegen sollten wir uns einmal anschauen welche Möglichkeiten wir haben ein Array mit einer Schleife auszugeben. Zu dem Zweck basteln wir uns erst mal ein neues, assoziatives Array mit einigen fiktiven Angaben und erzeugen das benötigte Objekt.
    PHP-Code:
    $person = array( "Vorname" => "Max",
                     
    "Nachname" => "Mustermann",
                     
    "Alter" => 39,
                     
    "Haarfarbe" => "Braun",
                     
    "Beruf" => "Rauhhaardackelzüchter" );

    $PersonObjekt = new ArrayObject$person );
    $zeiger $PersonObjekt->getIterator(); 
    Soweit gibt's hier nichts neues zu sehen. Schauen wir uns jetzt an, wie wir an unsere Daten kommen.

    Als foreach()-Schleife
    PHP-Code:
    $zeiger->rewind();
    foreach (
    $zeiger as $schluessel => $wert)
    {
        echo 
    $schluessel": " .$wert"<br>";

    Als for()-Schleife
    PHP-Code:
    for ($zeiger->rewind(); $zeiger->valid(); $zeiger->next())
    {
        echo 
    $zeiger->key(). ": " .$zeiger->current(). "<br>";

    Als while()-Schleife
    PHP-Code:
    $zeiger->rewind();
    while (
    $zeiger->valid())
    {
        echo 
    $zeiger->key(). ": " .$zeiger->current(). "<br>";
        
    $zeiger->next();

    Wie wir sehen bleibt sich bei foreach() alles beim alten. Kein Wunder, ist doch foreach() eigentlich die Ausgabemethode für Arrays.

    Bei der for()-Schleife setzen wir den Zeiger auf den Array-Anfang ($zeiger->rewind()) zurück und übernehmen diese Position als Startwert für die Schleife. Als Bedingung benutzen wir hier $zeiger->valid() um zu prüfen ob die aktuelle Zeigerposition auf ein valides Array-Element zeigt. Mit $zeiger->next() legen wir den Intervall fest. Die Ausgabe ist dann Element-Schlüssel ($zeiger->key()) und der Element-Wert ($zeiger->current()).

    Bei der while()-Schleife müssen wir etwas aufpassen, damit wir nicht durch Nachlässigkeit eine Endlosschleife produzieren. Hier wird nämlich als Bedingung geprüft: solange $zeiger->valid() True ist, führe die Schleife aus. Deswegen ist es zwingend notwendig, daß wir innerhalb der Schleifen den Zeiger immer um eine Position nach vorn schieben ($zeiger->next()), wenn die Ausgabe erfolgt ist. Nur so können wie sicherstellen das die Bedingung irgendwann False ist - nämlich dann, wenn wir an der letzten Position im Array angekommen sind und den Zeiger "über das Ende hinaus" schieben.

    Alles bis hierhin war (hoffentlich) einfach nachvollziehbar. Zugegeben, einen wirklichen Durchbruch gegenüber der prozeduralen Herangehensweise ist noch nicht so ganz zu erkennen. Allerdings ist es für komplexere Aufgaben zwingend erforderlich das man den Umgang mit den Basisfunktionen beherrscht. Denn ganz gleich welche Iterator Klassen aus der SPL wir benutzen, in allen wird auf eine sehr ähnliche, bzw. identische Weise navigiert. Schauen wir uns nun ein mehr praxisbezogenes Beispiel an.



    Mit Verzeichnissen arbeiten - DirectoryIterator

    Was für Arrays die ArrayIterator Klasse ist, ist für Verzeichnisse die DirectoryIterator Klasse. Diese Klasse stellt Methoden zu Verfügung mit der wir ohne großen Aufwand gängige Verzeichnis-Aktionen ausführen können. Schauen wir uns im Schnelldurchlauf mal die wichtigsten Methoden an, die weitestgehend selbsterklärend sind. Neben den üblichen 5 Verdächtigen der Iterator Klasse (siehe oben) stehen weiterhin zur Verfügung:
    • getFilename() - Der Dateiname ohne Pfad
    • getMTime() - Datum der letzten Modifikation
    • getPath() - Der Pfad zu einer Datei
    • getRealPath() - Der absolute Pfad zu einer Datei
    • getSize() - Dateigröße
    • isDir() - Gibt True zurück, wenn der Name ein Verzeichnis ist
    • isDot() - Gibt True zurück, wenn "." oder ".." gefunden wird
    • isFile() - Ist True, wenn es sich um eine Datei handelt
    • isReadable() - Ist True, wenn eine Datei lesbar ist
    • isWritable() - Ist True, wenn eine Datei schreibbar ist

    Die DirectoryIterator Klasse umfasst etwa dreimal soviele Methoden wie die hier gezeigten, aber das sind meiner Meinung nach die wichtigsten.

    Das Auslesen eines Verzeichnis ist sehr einfach und mit wenigen Zeilen Code erledigt.
    PHP-Code:
    $verzeichnis = new DirectoryIterator"testdateien/" );

    while (
    $verzeichnis->valid())
    {
        echo 
    $verzeichnis->current(). " (" .$verzeichnis->getSize(). ")<br>";
        
    $verzeichnis->next();

    Wir erzeugen ein Objekt von der DirectoyIterator Klasse und übergeben dabei den Verzeichnisname dessen Inhalt wir ausgeben lassen möchten. Die Struktur der while()-Schleife sollte nun bekannt sein. Zusätzlich lassen wir uns noch zu jeder Datei die Größe ausgeben, was für uns die Methode getSize() der DirectoyIterator Klasse übernimmt. Das Ergebnis sieht allerdings nicht sonderlich ansprechend aus, wie man im folgenden Listing sieht:
    Code:
    . (0)
    .. (0)
    bilder (0)
    controller.php (4901)
    includes (0)
    m3_saz.jpg (72517)
    mixed (0)
    whois.php (21563)
    whois.zip (3718)
    Da sind Dateien mit Ordnern vermischt und auch "." ".." sehen nicht sonderlich gut aus. Wir bekommen ausserdem nur die Dateien aus dem angegebenen Ordner, was meistens wenig nützlich ist. Um herauszufinden was in den anderen Ordnern steckt müssen wir anfangen eine umständliche Funktion zu schreiben, die uns rekursive durch die Verzeichnisse navigieren läßt. Für diesen Zweck gibt es ja auch die nötigen Boardmittel wie isDot() oder auch isDir().
    Aber muß es wirklich so kompliziert werden oder kommt uns da vielleicht wieder die SPL zu Hilfe? In der Tat wurde auch daran gedacht und die SPL stellt für das rekursive arbeiten die entsprechenden Klassen zur Verfügung. Um es genau zu sagen bietet die SPL zu jedem Iterator-Typ auch eine Recursive-Version der Klasse an. Wie praktisch das ist zeigt das nächste Beispiel...


    Verzeichnisse rekursive auslesen mit der RecursiveDirectoryIterator Klasse

    Die RecursiveDirectoryIterator Klasse bringt im Vergleich zur DirectoryIterator Klasse nur 2 neue Methoden mit, aber die sind überaus nützlich. Diese beiden Methoden sind:
    • hasChildren() - Liefert True, wenn ein "Kind" (Unterverzeichnis) vorhanden ist
    • getChildren() - Liefert den Namen vom "Kind" (Unterverzeichnis)

    Mit diesen beiden zusätzlichen Methoden können wir jetzt wirklich ganz bequem eine sehr übersichtliche Funktion erstellen, um rekursive durch Verzeichnisse zu navigieren. Here we go...

    PHP-Code:
    function VerzeichnisBaumRecursiveDirectoryIterator $zeiger )
    {
        echo 
    '<ul>';
        for (
    $zeiger->rewind(); $zeiger->valid(); $zeiger->next())
        {
            if (
    $zeiger->isDir() && !$zeiger->isDot())
            {
                echo 
    '<li><strong>' .$zeiger->getFilename(). '</strong></li>';
                if (
    $zeiger->hasChildren())
                {
                    
    $unterverzeichnis $zeiger->getChildren();
                    echo 
    '<ul>' VerzeichnisBaum$unterverzeichnis ) . '</ul>';
                }
            } elseif (
    $zeiger->isFile())
            {
                echo 
    '<li><em>'$zeiger->getFilename() . '</em></li>';
            }
        }
        echo 
    '</ul>'
    }

    VerzeichnisBaum( new RecursiveDirectoryIterator'testdateien/' ) ); 
    Die Basisversion dieser Funktion habe ich aus dem Buch "PHP 5 - Grundlagen und Profiwissen von Jörg Krause". Allerdings habe ich die Funktion etwas abgewandelt um sie verständlicher zu machen.
    Die Funktionsweise ist einfach und weitestgehend selbsterklärend. Beim Funktionsaufruf (ganz unten) wird das Objekt der RecursiveDirectoryIterator Klasse übergeben. Der Klasse selbst geben wir nur den Pfad und Verzeichnisname mit den wir durchlaufen möchten.
    Wie in der Funktion zu sehen ist prüfen wir ob der Zeiger auf einem Verzeichnis steht ($zeiger->isDir()) und geben den Element-Name ($zeiger->getFilename()) fett aus. Anschließend wird geprüft (mit $zeiger->hasChildren()) ob das Element (Verzeichnis) ein Kind (Unterverzeichnis) hat - trifft das zu, lesen wir den Namen des Kindes aus ($zeiger->getChildren()) und übergeben diesen Namen an die Funktion, die sich selbst mit dem Unterverzeichnisname aufruft. Am besten zwei oder drei mal diese Funktion durchlesen und nachvollziehen um das Prinzip zu verinnerlichen. Viel einfacher kann man Verzeichnisse nicht rekursive auslesen, oder?! Hmm, oder vielleicht doch!?!

  2. #2
    TP-Specialist Avatar von phpBuddy
    Registriert seit
    Aug 2004
    Ort
    Kaiserslautern
    Beiträge
    4.678

    Standard PHP Library - Teil 2

    Zip-Dateien on-the-fly erstellen

    Bevor wir mit den Iterator-Klassen weiter machen, wollen wir einen kurzen Abstecher zu einer anderen, sehr nützlichen, neuen Klasse in PHP 5 machen: ZipArchive

    Mit der ZipArchive Klasse kann man auf eine wirklich sehr einfache Art und Weise Zip Dateien erstellen, verändern und auch wieder entpacken. Das erforderte früher mehr oder weniger komplizierte externe Klassen mit sehr viel Code, in denen nur die wenigsten verstanden was da eigentlich vor sich geht. Das ändert sich grundlegend mit PHP 5. Die Methoden dieser Klasse sind sehr intuitiv und einfach zu verstehen; hier ein Überblick der wichtigsten Methoden:
    • addEmptyDir() - Fügt einen leeren Ordner hinzu
    • addFile() - Fügt eine Datei hinzu
    • addFromString() - Fügt einen Datei aus Text hinzu
    • close() - Schließt eine offene Zip-Datei
    • extractTo() - Entpackt ein Archiv an eine bestimmte Position
    • open() - Öffnet eine Zip-Datei, bzw legt eine neue Zip-Datei an

    Das ist nur ein kleiner Teil der Methoden der ZipArchive Klasse. Desweiteren stehen Methoden zur Verfügung um Kommentare anzufügen/auszulesen, Index und Namen zu verändern, usw. Schauen wir uns ein sehr einfaches Beispiel an, wie man mit sehr wenigen Zeilen Code eine Zip-Datei erstellen und auch wieder entpacken kann. Das kann sehr nützlich sein um Backups zu erstellen und wieder herzustellen.

    Das Listing um eine neue Zip-Datei zu erstellen sieht wie folgt aus:
    PHP-Code:
    $zip = new ZipArchive;
    $resource $zip->open'testarchiv.zip'ZipArchive::CREATE );
    if (
    $resource === TRUE)
    {
        
    $zip->addFromString'test.txt''Hier steht ein beliebiger Text.' );
        
    $zip->addFile'testdateien/controller.php''config/controller.php' );
        
    $zip->addFile'testdateien/m3_saz.jpg''bilder/blindschleiche.jpg' );
        
    $zip->addFile'testdateien/whois.php''whois.php' );
        
    $zip->addFile'testdateien/whois.zip''whois.zip' );
        
    $zip->close();

    In Zeile 1 erzeugen wir eine neue Instanz der ZipArchive Klasse. Anschliessend erstellen wir mit der Zeile
    PHP-Code:
    $resource $zip->open'testarchiv.zip'ZipArchive::CREATE ); 
    eine neue Zip-Datei und merken uns den Status (True oder False) von dem Vorgang. Wichtig hier ist der 2. Parameter in $zip->open(). Durch den Zusatz ZipArchive::CREATE teilen wir der Klasse mit, daß wir eine neue Zip-Datei erstellen möchten. Ohne diesen Zusatz würde die Klasse versuchen die Datei testarchiv.zip zu öffnen, was unweigerlich in einem Fehler endet, da diese Datei nicht existiert. Möchten wir hingegen eine bereits existierende Zip-Datei öffnen, weil wir z.B. Datei hinzufügen wollen, muß der Zusatz weggelassen werden, da sonst die Zip-Datei überschrieben wird!

    Nachdem geprüft wurde ob die Datei erfolgreich angelegt wurde, fügen wird Dateien zu unserem Zip-Archiv hinzu. Als ersten benutzen wir $zip->addFromString() um eine Datei aus einer Variablen anzufügen. Wie wir sehen bestimmen wir als ersten Parameter den Dateinamen in der Zip-Datei und als 2. Parameter übergeben wir den String, bzw die Variable die den String beinhaltet.
    Mit der Methode $zip->addFile() erweitern wir unser Zip-Archiv um weitere Dateien. Dabei stellt der erste Parameter die Quelldatei (ggfs mit Pfad) auf dem Server dar, während der 2. Parameter der Pfad und Dateiname in dem Archiv darstellt. Wie wir sehen können wir Pfad (Ordner-Struktur im Archiv) und Dateiname frei vergeben und müssen uns nicht an die Struktur auf dem Server halten. Sind alle Dateien hinzugefügt, wird das Archiv mit $zip->close() wieder geschlossen und unsere Zip-Datei ist fertig. Um Problemen mit Safe_Mode aus dem Weg zu gehen empfiehlt es sich, unmittelbar nach dem close() die Dateirechte mit CHMOD anzupassen.

    Das entpacken einer Zip-Datei ist genauso einfach:
    PHP-Code:
    $zip = new ZipArchive;
    if (
    $zip->open'testarchiv.zip' ) === TRUE)
    {
        
    $zip->extractTo'testdateien/' );
        
    $zip->close();

    Als erstes wieder ein neues Objekt von der ZipArchive Klasse erzeugen. In der if() wird geprüft ob das öffnen ($zip->open()) der Zip-Datei erfolgreich war. (Kein 2. Parameter wie beim erstellen!)
    Dann entpackt man den Inhalt aus der testarchiv.zip mithilfe der Methode $zip->extractTo() in den Zielordner, was in unserem Fall testdateien ist. Die geöffnete Datei mit $zip->close() schliessen und das war's! Kinderleicht, nicht wahr?!

    Jetzt wo wir gesehen haben wie einfach es ist Zip-Dateien on-the-fly zu erstellen und wieder zu entpacken, kombinieren wir das mal mit den Fähigkeiten unseren DirectoryIterator Klassen.

    Mal eine kleine Zwischenfrage: Was glaubst Du wie viele Zeilen Code wir brauchen um uns mithilfe der neuen ZipArchive Klasse und den Iterator Klassen der SPL ein Backup Script zu schreiben das uns ein Datei-Backup von unserer -sagen wir mal- 6-fach verschachtelte Verzeichnisstruktur erstellt? 25? 35? 50? mehr??

    Fast, es sind ziemlich genau 7 Zeilen!



    Die Kernfunktion unseres Datei-Backup Scripts

    Ok zugegeben, das mit den 7 Zeilen war nicht leicht zu erraten, weil dazu eine weitere Iterator Klasse erforderlich ist die wir uns noch gar nicht angeschaut haben. Ebenso wurde auch noch nicht erwähnt das man Objekte einer Iterator Klasse beim Instanziieren einer anderen Iterator Klasse an diese übergeben kann, was den Umgang mit den Klassen wesentlich erleichtert und Schreibarbeit spart.

    Das Listing des Backup Scripts zum erzeugen einer Zip Datei einer verschachtelten Verzeichnisstruktur:
    PHP-Code:
    $verzeichnis =  new RecursiveIteratorIterator(
                    new 
    RecursiveDirectoryIterator'testdateien/' ), true );
    $zip = new ZipArchive;
    $resource $zip->open'backup.zip'ZipArchive::CREATE );
    if (
    $resource === TRUE)
    {
        foreach ( 
    $verzeichnis as $datei )
        {
            
    $zip->addFile$datei$datei );
        }
    }
    $zip->close(); 
    Im Prinzip ist das ganze Listing weitestgehend identisch mit dem Zip-Archiv Beispiel von eben. Einzig die erste Zeile ist etwas anders im Vergleich zu den vorherigen Beispielen, aber hier geschieht die eigentliche Arbeit. Aufgrund der Länge der Zeile habe ich sie umgebrochen um sie übersichtlicher zu machen. Werfen wir mal einen genaueren Blick darauf...

    PHP-Code:
    $verzeichnis =  new RecursiveIteratorIterator( new RecursiveDirectoryIterator'testdateien/' ), true ); 
    Die innere Instanziierung der RecursiveDirectoryIterator Klasse ist nicht neu, das hatten wir weiter oben schon unter die Lupe genommen. Was hier jetzt aber neu ist, ist die Klasse RecursiveIteratorIterator der, bei dessen Instanziierung, das Object der RecursiveDirectoryIterator Klasse übergeben wird.
    Wie wir oben gelernt haben, hat die RecursiveDirectoryIterator Klasse die Methoden hasChildren() und getChildren(), womit sich ermitteln lässt ob ein Verzeichnis weitere Unterverzeichnisse hat. Hier setzt die RecursiveIteratorIterator Klasse an, denn ganz offensichtlich erkennt diese Klasse selbstständig ob es Kinder gibt und beginnt ggfs die rekursive Iteration rekursive zu iterieren. (Geiler Satz, gelle?! )
    Hier ist eine kurze Übersicht der Methoden die dafür verantwortlich sind:
    • beginChildren()
    • beginIteration()
    • callGetChildren()
    • callHasChildren()
    • endChildren()
    • endIteration()
    • getDepth()
    • getInnerIterator()
    • getSubIterator()
    • nextElement()

    Das True beim Aufruf könnte man in diesem Fall auch weg lassen, da es für das erstellen der Zip-Datei nicht erforderlich ist. Wird beim Aufruf True angegeben, wird auch der Name des Kindes (Unterverzeichnis) ausgegeben. Das kann nützlich und sinnvoll sein wenn z.B. eine Ordnerstruktur auf dem Screen ausgeben werden soll.

    Schon beeindruckend wie einfach man so ein kleines Backup Script schreiben kann. Allerdings ist die Arbeitsweise doch etwas unbefriedigend. Das Script würde nämlich gnadenlos alles in die Zip-Datei packen was ihr auf dem Weg bei der rekursiven Iteration über den Weg läuft. Wirklich sinnvolle Backups kann man aber eigentlich nur dann machen, wenn wir bestimmte Dateien ausklammern könnten (z.B. htaccess Dateien, Log-Files, usw.) oder nur bestimmte Dateien in's Backup aufnehmen.
    Wenn wir eins bis hierhin gelernt haben dann ist es, daß Verlaß auf die SPL ist. Wie nicht anders zu erwarten gibt es nämlich auch hier eine vorgefertigte Lösung und die heisst...



    Inhalte filtern mit der FilterIterator Klasse

    Die FilterIterator Klasse kommt verhältnismässig bescheiden daher, denn neben den 5 Standard Iterator Methoden verfügt diese Klasse nur über einen Konstruktor und diese Methoden:
    • getInnerIterator() - Ermittelt an welcher Position der Zeiger im inneren Iterator steht
    • accept() - Nimmt eine Bedingung auf um zu entscheiden ob das gegenwärtige Element (current()) gefiltert werden soll


    Nichts desto Trotz ist der Einfluß dieser Klasse gewaltig, denn mit ihr können wir genau festlegen was gefiltert wird und was nicht. Um eine (Filter)Bedingung an die FilterIterator Klasse zu übergeben, müssen wir eine eigene Klasse schreiben und die FilterIterator Klasse erweitern.

    Das Listing der FilterIterator Klasse Erweiterung:
    PHP-Code:
    class DateiFilter extends FilterIterator
    {
        private 
    $erweiterung;
        private 
    $zeiger;

        public function 
    __construct$iterator$erweiterung )
        {
            
    parent::__construct$iterator );
            
    $this->zeiger $iterator;
            
    $this->erweiterung $erweiterung;
        }

        public function 
    accept()
        {
            if (!
    $this->zeiger->isDir())
            {
                if (
    gettype$this->erweiterung ) == "array")
                {
                    
    $ArrayObjekt = new ArrayObject$this->erweiterung );
                    
    $zeiger $ArrayObjekt->getIterator();
                    
    $zeiger->rewind();
                    foreach (
    $zeiger as $schluessel => $wert)
                    {
                         
    $erweiterung array_reverseexplode'.'$this->current() ) );
                         if (
    $erweiterung[0] == $wert$erweiterungen[] = $this->erweiterung;
                    }
                    return 
    $erweiterungen;
                }
                else
                {
                    
    $erweiterung array_reverseexplode'.'$this->current() ) );
                    return 
    $erweiterung[0] == $this->erweiterung;
                }
            }
            return 
    true;
        }

    Vielen Dank an Mark (webcreate) für die Dateiendung-Array Erweiterung

    Da für diesen Artikel ein gutes Verständnis der OOP vorausgesetzt wird sollten hier eigentlich keine großen Erklärungen nötig sein. Der Konstruktor erwartet zwei Parameter: 1) die zu iterierende Resource und 2) die erlaubte Datei-Endung(en).
    Die Methode accept() in unserer Klasse wurde nicht willkürlich so genannt, sondern muß so heissen, damit wir die Methode accept() der FilterIterator Klasse überladen können.

    Um den neuen Filter in Aktion zu sehen rufen wir unsere Klasse mit folgendem Code auf:
    PHP-Code:
    $verzeichnis =  new DateiFilter(
                    new 
    RecursiveIteratorIterator(
                    new 
    RecursiveDirectoryIterator'testdateien/' ) ), 'jpg' );

    foreach (
    $verzeichnis as $datei)
    {
        echo 
    $datei"<br>\n";

    Um mehrere Dateiendungen aufzulisten übergeben wir beim Aufruf ein Array:
    PHP-Code:
    $verzeichnis =  new DateiFilter(
                    new 
    RecursiveIteratorIterator(
                    new 
    RecursiveDirectoryIterator'testdateien/' ) ), array( 'jpg''html' ));

    foreach (
    $verzeichnis as $datei)
    {
        echo 
    $datei"<br>\n";

    Die inneren Instanziierungen kennen wir vom letzten Beispiel. Das so erzeugte Objekt übergeben wir, zusammen mit der erlaubten Datei-Endung (jpg), an unsere DateiFilter Klasse. Anschliessend geben wir in einer einfachen foreach() sämtliche gefundene Dateien aus die auf jpg enden.

    Statt dem echo() in der foreach() könnten wir auch genauso gut, nachdem wir eine Zip-Datei geöffnet/angelegt haben, das $zip->addFile() dort stehen haben oder jede beliebige andere Aktion hier ausführen. Selbstverständlich könnten wir die Methode accept() auch erweitern, so daß z.B. mit $zeiger->getMTime() geprüft wird ob $zeiger->current() neuer oder älter als eine Datei im Zip-Archiv ist und auf diese Weise so etwas wie ein Inkrementelles Backup Script erzeugen.



    Fazit und Schlußwort

    Als erstes möchte ich im Schlußwort noch auf eine "Kleinigkeit" hinweisen. Während des ganzen Artikels sprach ich aus Gründen der Einfachheit, um den Lernenden nicht zu verwirren, von der Iterator "Klasse". In Wirklichkeit ist es aber ein Interface das in die anderen Iterator Klassen (wie z.B. DirectoryIterator) implementiert wird. Das ist dahingehend wichtig, als das man sich eigene Iterator Klassen erstellen kann und durch das implementieren des Iterator Interface auf die Iterations-Kernfunktionen zugreifen kann. Es ist also mehr als eine einfache Vererbung.

    Jetzt aber wieder zurück zum Thema...
    Die Möglichkeiten mit den Iterator Klassen sind schier unbegrenzt und jeder sollte sich etwas Zeit nehmen um ein wenig damit zu experimentieren. Die hier gezeigten Beispiele sind nur an der Oberfläche gekratzt, um einen generellen Einstieg etwas zu erleichtern.
    Viele werden die Notwendigkeit jetzt noch nicht so deutlich erkennen, aber Anfang nächsten Jahres läuft der Support für PHP 4 aus und immer mehr Provider werden nur noch PHP 5 anbieten, welches wesentlich objektorientierter arbeitet als seine Vorgänger. Das wird sich über kurz oder lang auch auf MySQL auswirken, wenn sich das objektorientierte MySQLi durchsetzen wird.
    Ausserdem wird ein Code mithilfe der SPL übersichtlicher und einheitlicher, was es einem erleichtert sich in fremden Code zurecht zu finden. Jeder der schon mal fremde Scripts anpassen wollte wird das sicherlich kennen. Da kämpft man mehr damit sich durch die Logik und Struktur des fremden Code zu hangeln, statt sich auf das wesentliche zu konzentrieren. Die SPL versucht hier einen Standard in's Spiel zu bringen, von dem wir alle profitieren könnten.

    Dieser Artikel war sehr lang, deswegen möchte ich auf weitere Worte verzichten. Im Anschluß gibt es noch einige Tipps um der SPL wichtige Informationen zu entlocken.



    Tipps zur SPL

    Die erste Anlaufstelle um an Informationen zu kommen und um die Zusammenhänge der einzelnen Klassen zueinander zu verstehen ist die Webseite des Entwicklers.



    Um festzustellen welche Klassen mit PHP installiert wurden einfach eine PHP Datei mit folgenden Inhalt auf dem Server ausführen.
    PHP-Code:
    echo "<pre>" .print_rget_declared_classes(), true ). "</pre>"
    Alle Methoden einer Klasse ermitteln:
    PHP-Code:
    echo "<pre>" .print_rget_class_methods"DirectoryIterator" ), true ). "</pre>"

    Ich hoffe dieser Artikel konnte den ein oder anderen dazu ermutigen sich etwas mit dieser tollen Erweiterung von PHP 5 zu beschäftigen und wünsche Euch allen ein fröhliches iterieren

    Vielen Dank an Mark (webcreate) für das "Probelesen" und den guten Vorschlag (inklusive Code) mit der Dateiendung-Array Erweiterung!

  3. #3
    TP-Urgestein Avatar von webcreate
    Registriert seit
    Nov 2003
    Ort
    NRW
    Beiträge
    11.661
    Der größere Dank geht an Dich, für dieses spitzen Tutorial.
    Da macht auch das "Probelesen" Spaß.
    Gruß Mark

    webcreate IT SOLUTIONS
    www.webcreate-nrw.de

    Photoblog....|....flickr

  4. #4
    TP-Specialist Avatar von phpBuddy
    Registriert seit
    Aug 2004
    Ort
    Kaiserslautern
    Beiträge
    4.678
    Zitat Zitat von webcreate Beitrag anzeigen
    Der größere Dank geht an Dich, für dieses spitzen Tutorial.
    Da macht auch das "Probelesen" Spaß.
    Wenn der ein oder andere davon was lernt hat es sich ja schon gelohnt. Ausserdem war es eine gute Gelegenheit selber etwas tiefer in die Materie zu schauen.
    Aber ich muß schon sagen, wow! Jetzt wo ich es selbst das erste mal "am Stück" im Forum sehe muß ich zugeben das es ganz schön lang ist.

    Das "Probelesen" macht sicher mehr Spaß ohne Gepöbel vorher
    Naja, meine "Drohung"..err Idee, hab' ich ja schon per PN geäußert. Ob ich Dich deswegen dann wieder nerve oder ein anderes "Opfer" suche wird sich zeigen

  5. #5
    TP-Junior
    Registriert seit
    Mar 2007
    Ort
    Berlin
    Beiträge
    17
    Hallo.
    Ersteinmal vielen Dank für dieses Tutorial. Ich habe leider erst den Anfang gelesen.
    Na ja das mühevolle Raussuchen der vorhandenen Klassen, war nicht ganz so einfach, deswegen hab ich nen bisschen rumgespielt, damit das Testen etwas schneller geht (eigentlich war ich schon zu müde um das Tutorial weiter zu verfolgen, weshalb ich "rumspielte"). Rausgekommen dabei ist jedoch folgendes, was ich gerne zur Verfügung stellen möchte, falls es jemandem hilft.
    PHP-Code:
    <?php
    /**
    * Script zum Schnelltesten ob benoetigte Klassen vorhanden sind
    */
    ob_start();
    ######### KONFIGURATION ###############
    // Array zusammenstellen;
    $reqClasses = array(
        
    'ArrayObject',
        
    'ArrayIterator',
        
    'RecursiveDirectoryIterator',
        
    'RecursiveIteratorIterator',
        
    'FilterIterator',
        
    'ZipArchive'
    );
    ############### ENDE ##################
    ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>QuickClassCheck</title>
    </head>
    <body>
    <div style="background-color:#FFFF99;border:1px solid #000000; width:270px; text-shadow:#009900;">
    <div align="left" style="font-weight:normal; background-color:#CCCCCC;">&nbsp;Teste ob ben&ouml;tigte Klassen voranden sind:</div><br />
    <?php
    // Anzahl der Elemente zaehlen
    $num count($reqClasses);
    // Errorvariable initialisieren
    $err 0;
    for(
    $i 0$i $num$i++) {
        echo(
    "<span style='text-decoration:underline;'>&nbsp;".$i." | ".trim($reqClasses[$i])."</span>");
        if(
    class_exists(trim($reqClasses[$i]))){
            echo(
    " <span style='color:#000000;background-color:#00FF00;font-size:10pt;'>&nbsp;EXISTS&nbsp;</span><br />\n");
            continue;
        }
        echo(
    " <span style='color:#FFFFFF;background-color:#FF0000;font-size:10pt;'>&nbsp;DON'T EXISTS&nbsp;</span><br />\n");
        ++
    $err;
    }
    echo(
    "<br />\n".
    (
    $err == 0
    ?
    "<div style='color:#000000;background-color:#00FF00;'>&nbsp;Test bestanden&nbsp;</div>"
    :
    "<div style='color:#FFFFFF;background-color:#FF0000;'>&nbsp;Test nicht bestanden (".$err" fehlende Klasse".($err == 1?null:"n").")&nbsp;</div>"
    ));
    ob_end_flush();
    ?>
    </div>
    </body>
    </html>
    Nun ja. Das erstmal zum Anfang. Ich hab aber ein Problemchen.
    Ich testete das auf XAMPP und alle benötigten Klassen waren vorhanden.
    Da ich das, was ich hier lerne jedoch nicht für mich behalten möchte, testete ich es auch gleich auf unserem Produktivserver. Dort fehlte aber die Zip-Klasse, weshalb ich schon googlete und irgendwie nur die Auskünfte bekam, dass man PHP irgendwie damit kompilieren muss. Ich bin zwar nicht der Serveradmin aber ich stelle mir die Frage, wie man genau soetwas anstellen muss, damit man die benötigten Klassen zur Verfügung hat. Meines Wissens kommen wir nicht mal an die php.ini ran, weil der Server (den wir für uns alleine nutzen) über Plesk verwaltet wird.
    Ich würde aber nicht meine Hand dafür ins Feuer legen, dass der Serveradmin den Server nur darüber verwaltet. Ich weiß es einfach nicht. Ich würde ihn sofort fragen, wenn ich ihn erreichen würde. Meine Frage ist jetzt nun ersteinmal, ob man PHP komplett neu installieren muss und mit bestimmten Parametern kompilieren muss, oder wie soetwas geht. Ich würde nämlich ungern auf solche Funktionalität verzichten. Ich hab aber überhaupt kein Plan, wie man PHP auf nen Server bearbeitet. Von Servern im Allgemeinen hab ich auch nicht viel Ahnung. Wenn sich jemand die Mühe machen würde und mir erklärte, was man tuen muss um Klassen (respektive auch Funktionen) hinzuzufügen. Auch würde mich interessieren welche Risiken soetwas birgt (Sicherheit, Probleme, ect.), weil nicht jeder nen eigenen Server besitzt und die Anbieter da evtl. nicht mit sich reden lassen wollen. Dabei wären eventuelle Workarounds oder Alternativen ganz hilfreich, wenn es sie denn gibt, denn soviel Fachenglisch versteh ich leider noch nicht so wirklich.
    Geändert von ronsn (15.08.2007 um 10:27 Uhr)

  6. #6
    TP-Specialist Avatar von phpBuddy
    Registriert seit
    Aug 2004
    Ort
    Kaiserslautern
    Beiträge
    4.678
    Hallo ronsn,

    wie man nun genau ein Paket bzw Modul nachinstalliert kann ich dir auch nicht sagen, aber sicher einer der Linux-Spezies hier
    Ich weiß nur, daß es keine große Sache sein kann (vermutlich 1-Zeiler in der Shell), weil ich anfangs bei all-inkl auch einige Klassen nicht zur Verfügung hatte. Eine kurze Email hat gereicht und kurz danach (weniger als 30 Minuten) kam die Antwort, daß das Modul nachinstalliert wurde. Seit dem läuft auch alles perfekt.

    Falls Du nach Alternativen zur Erstellung von Zip-Archiven suchst kannst Du jederzeit eine der vielen Klassen benutzen die es im Web gibt. Das ist dann zwar alles nicht mehr sooo komfortabel wie es das mit den PHP 5 eigenen Klassen ist, aber auch das funktioniert problemlos. Steffen hat hier im Forum mal eine Zip-Klasse zu Verfügung gestellt, die immer sehr zuverlässig funktioniert hat.

    Deine Bedenken bezüglich Sicherheit/Probleme beziehst Du worauf? Das neu-kompilieren von PHP?


    [edit]
    Danke für dieses nette Klassen-Check Script. Wirklich 'ne gute Idee und sehr komfortabel!

  7. #7
    TP-Junior
    Registriert seit
    Mar 2007
    Ort
    Berlin
    Beiträge
    17
    Hallo nochmal.
    Mit den Risiken meinte ich eigentlich die Bedenken der Anbieter.
    Wenn eine Klasse nicht vorhanden ist, so stelle ich mir die Frage, warum das so ist.
    Und eine mögliche Antwort wäre ja, dass dadurch Sicherheitsprobleme entstünden, wenn die Klasse installiert wäre.
    Eine andere mögliche Antwort wäre, dass es Performance-Probleme gäbe, die dadurch entstünden.
    Ich hab von sowas absolut keine Ahnung. Sorry.

    Post Scriptum:
    Es freut mich, dass dir das kleine Script gefällt. Ich hatte schon Angst ausgelacht zu werden, was ich da für ein "Billig-Script" in soeinem fortgeschrittenen Tutorial präsentiere. Ob ich schon so fortgeschritten bin, weiß ich nicht.
    Mit der OOP habe ich erst vor 3 Wochen begonnen. Die größten Schwierigkeiten waren/sind, dass so viele Fachworte für ein und dieselbe Sache existieren, was es einem nicht gerade leicht macht.
    Nun ja. Schön, dass es solche Leute wie dich gibt, denen man etwas über die Schulter schauen kann.
    Danke nochmal!
    Geändert von ronsn (15.08.2007 um 11:18 Uhr) Grund: Orthographie

  8. #8
    TP-Specialist Avatar von phpBuddy
    Registriert seit
    Aug 2004
    Ort
    Kaiserslautern
    Beiträge
    4.678
    Also ich denke nicht das aus Gründen der Sicherheit solche Klassen nicht verfügbar sind. Da wird es wohl eher um die Performance und Resourcen -und damit um Kosten- gehen. Jede Klasse/Modul die integriert ist belegt natürlich auch dementsprechend Speicher. Das mag bei einem eigenen Server nicht schlimm sein, weil es nur einige (hundert) KB sind. Hat man da aber 200 Kunden auf einem Server (Shared Webspace) und jeder hat da seine eigene Config, dann kann sich das sehr wohl gemerkbar machen. Schliesslich müsste mehr Speicher verbaut werden, damit jeder soundsoviel zugesicherten Speicher auch erhält - das ist also ein Kostenfaktor. Die allermeisten die Mietwebspace haben sind wohl Leute die ohnehin niemals solche Klassen in Anspruch nehmen werden, von daher wäre es unnötig, wenn diese Klassen standardmäßig Resourcen belegen.

    Ein anderer Grund könnte Performance sein. Klar, daß so eine Zip Angelegenheit Rechenpower braucht. Erlaubt man jetzt jedem sich ständig Zip's zu erstellen, könnte dabei der Server in die Knie gehen. Ich habe -als Beispiel- bei all-inkl das PrivatPlus Paket mit 10 GB Space. Stell Dir mal vor ich habe da dicke fette Galerien liegen, die insgesamt 3 GB umfassen. Jetzt hätte ich Paranoia und würd' jeden Tag auf die oben beschrieben Weise alle Galerien sichern. Ist wohl klar das in der Zeit der Rechner stärker belastet wird. Machen das jetzt andere auf dem gleichen Server genauso, ist der Server mehr down als up

    Gute Provider, stellen einem sowas auf Anfrage zur Verfügung. Sie werden aber einen Dreck tun und es von sich aus anbieten Schick einfach mal eine mail an den Support deines providers und frag höflich an, ob diese Option zur Verfügung steht und ob man die benötigten Module nachinstallieren kann.

  9. #9
    TP-Junior
    Registriert seit
    Mar 2007
    Ort
    Berlin
    Beiträge
    17
    Dankesehr. Ich hab zwar auf die Waage geklickt, weils in den NUB's so steht, aber ich hab das Gefühl, dass das irgendwie niemand nutzt. Ich weiß nämlich gar nicht, wo man soetwas sehen könnte. Deswegen hier nochmal: Danke!

  10. #10
    TP-Specialist Avatar von phpBuddy
    Registriert seit
    Aug 2004
    Ort
    Kaiserslautern
    Beiträge
    4.678
    Hallo ronsn,
    keine Ursache Info zu Bewertungen findest Du hier. Derjenige bekommt das schon mit ob und wie Du ihn bewertet hast, weil die Bewertungen im Kontrollzentrum stehen.

  11. #11
    TP-Newbie
    Registriert seit
    Sep 2007
    Ort
    Köln
    Beiträge
    1
    Danke für das Tutorial, war genau das was ich gesucht habe.
    Ich habe das Buch "PHP 5 aus erster Hand", da ist das Thema Iteratoren nur ganz leicht angerissen daher hatte ich das ein bisschen übersehen, da war das hier eine sehr gute Einleitung.

    Ich hab mal eine Klasse daraus gemacht, so wie ich sie brauche.

    Man kann das ganze hier runterladen:
    http://www.geoseo.org/web_pro/Zip%20...wnload,30.html
    Geändert von fritze (08.09.2007 um 13:44 Uhr)

  12. #12
    TP-Newbie
    Registriert seit
    Mar 2008
    Beiträge
    1

    Update Verzeichnisbaum

    Auch wenn dieser Thread schon älter ist, hat er mir heute sehr geholfen. Ich habe die Funktion Verzeichnisbaum etwas verändert und sie vor allem HTML-konform gemacht. Das Problem bei dem Originalskript ist, dass bei leeren Verzeichnissen und generell folgendes Konstrukt entsteht:

    HTML-Code:
    ...<li>BLA</li></ul><ul></ul><ul><li>BLUB...
    Das ist allerdings nicht standardkonform, obwohl es die Browser richtig anzeigen. ULs dürfen nicht leer sein und dürfen nicht so verschachtelt werden. D.h. eine neue UL muss innerhalb einer anderen in einem LI - Tag gestartet werden. Meine neue Funktion sieht dementsprechend aus:

    PHP-Code:
    function directoryTreeRecursiveDirectoryIterator $path ) {
            
        
    $first true;
                    
        for (
    $path->rewind(); $path->valid(); $path->next()) {
                
        if ( 
    $path->isDir() && !$path->isDot() ) {
                        
            if (
    $first) { print "<ul>"$first false; }
            
                
    $file    $path->getFilename();
                print 
    '<li>';
                print 
    $file;
                            
                if (
    $path->hasChildren()) {
                                
                    print 
    directoryTree($path->getChildren());
                            
                }
                            
                print 
    '</li>';
                        
            }
                        
        }
            
        if (!
    $first) print "</ul>";
                
    }
            
    directoryTree(new RecursiveDirectoryIterator("/" )); 
    Sie ist etwas abgewandelt auch dahingehend, dass sie nur Verzeichnisse anzeigt. Sollten auch die Dateien angezeigt werden, einfach den entsprechenden Part der Originalfunktion einfügen.

    Viel Spaß damit
    Phil


LinkBacks (?)

  1. 12.09.2007, 16:49

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Stichworte


LinkBacks (?)

  1. 12.09.2007, 16:49

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

     

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51