• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Verständnisfrage zu Schleife

Space Vampire

Senior HTML'ler
Ich benutze des Öfteren mal eine Schleife, die ich mal in irgendeinem Forum abgegriffen habe.
Sie liest ein Verzeichnis ein und erzeugt ein Array aus dessen Inhalt.
Ich habe immer verstanden, was sie macht, und bis zu einem gewissen Grad auch wie sie es macht.
Allerdings bei einigen Zeilen nicht zur Gänze.

Bisher hat es mich nie interessiert, aber inzwischen haben meine PHP-Kentnisse ein Niveau erreicht, wo es mich doch fuchst, dass ich diese Schleife nicht wirklich verstehe.
Vielleicht mag mir mal jemand erklären, was genau sie macht.

Nachfolgend der Code, mit Anmerkungen, wie ich ihn zu verstehen glaube oder auch nicht.

PHP:
// Pfad zum einzilesenden Verzeichnis
$dir = "verzeichnis/pfad/"; 

// Ein neues, leeres Array wird definiert
$files = array();

// Das Verzeichnis wird Geöffnet und in der variable $h definiert.
// Nach meinem Verständnis dürfte das noch kein Array sien, sonst wäre der Rest überflüssig(?)
$h = opendir($dir);

// Das geöffnete Verzeichnis ($h) wird in die Variable $file gelesen (immer noch kein Array[?])
// Die while-Schleife tastet den Verzeichnisinhalt Element für Element ab
// Die Schleife endet, wenn die Abfrage ins Leere greift(?)
while(($file = readdir($h)) !== false) { 

// Die nachfolgende if-Schleife verstehe ich garnicht.
// Ich denke, dass sie ebenfalls feststellt, wann die letzte Datei erreicht ist.
// Aber das macht doch bereits die while-Schleife, oder?
// BESONDERS DIE BEDINGUNG GIBT MIR RÄTSEL AUF!!
// WAS BEDEUTET '.' bzw. '..' ?
	if($file == '.' || $file == '..') { 
		continue; 
	} 

// Hier wird nun das Array mit dem Verzeichnisinhalt gefüllt
	$files[] = $file;
}

Ich hoffe, es hat jemand die Zeit und die Lust, mir das etwas näher zu erklären.
Vielen dank im Voraus :)
 
Werbung:
Zu dem readdir:
Dort wird so lange weiter gemacht, solange $file !== false ist. $file kriegt seinen wert aus dem return von readdir. Readdir geht bei jedem Aufruf eine Datei weiter nach vorn im ordner. Wenn keine Datei mehr da ist gibt readdir false zurück (vergleiche PHP: readdir - Manual)

Beim auslesen werden noch 2 besondere Dateien ausgelesen "." ist der aktuelle Ordner. Die "Datei" ".." steht für: Ein Verzeichnis nach oben wechseln. Diese Dateien will man sich im Normal-Fall nicht anzeigen lassen, weswegen in dieser Abfrage die Schleife für diese Datei übersprungen wird (mit continue). Die Abfrage könnte auch folgendermaßen lauten und wäre meiner Meinung nach "schöner"

PHP:
  if($file != "." && $file != "..") {
    $files[] = $file;
    // Möglichkeit 2, welche ich bevorzuge wäre folgende
    // array_push($files, $file);
  }
 
Eventuell noch die Ergänzung
PHP:
  if($file != "." && $file != ".." $$ !stristr($file,".ht")) {
    $files[] = $file;
    // Möglichkeit 2, welche ich bevorzuge wäre folgende
    // array_push($files, $file);
  }
Damit .htaccess Dateien nicht ausgegeben werden, da stehen manchmal Passwörter oder Usernamen drinnen....
 
Zuletzt bearbeitet von einem Moderator:
Werbung:
Gilles schrieb:
Die Abfrage könnte auch folgendermaßen lauten und wäre meiner Meinung nach "schöner"

Meiner Meinung nach auch, weil continue im Grunde ein Sprungbefehl ist. Andererseits helfen continue und auch return dabei, Funktionen nicht zu weit „nach rechts“ wachsen zu lassen, was ehrlich gesagt auch nicht ganz schlecht ist. Ich würde das im Zweifel nicht zu eng sehen.

Entschuldigung für das sehr weltfremde Beispiel.

PHP:
function isPositiveAndEven($number)
{
    if (!is_int($number)) {
        return false;
    }

    if ($number < 0) {
        return false;
    }

    if ($number % 2 !== 0) {
        return false;
    }

    return true;
}

function isPositiveAndEven2($number)
{
    $ret = false;

    if (is_int($number)) {
        if ($number >= 0) {
            if ($number % 2 === 0) {
                $ret = true;
            }
        }
    }

    return $ret;
}

var_dump(isPositiveAndEven( 2), isPositiveAndEven2( 2),
         isPositiveAndEven(-2), isPositiveAndEven2(-2));

Prinzipiell bin ich aber wie gesagt auch eher ein Verfechter der Schreibweise von isPositiveAndEven2. Aber wenn man Bücher wie dieses liest, wird man weich und sagt sich: Wer bin ich denn, Sachen besser zu wissen als die Leute, die es erfunden haben. :)

Dennis Ritchie, 1941-2011: Computer scientist, Unix co-creator, C programming language designer - Boing Boing :(

PHP:
// Das ist eine Verzeichnisangabe relativ zum „working directory“ des Scripts.
// Das ist in der Regel das Verzeichnis der zuerst aufgerufenen (hinsichtlich
// Includes) Script-Datei. Das konkrete working directory kann mit getcwd ausge-
// gegeben werden
$dir = 'verzeichnis/pfad';

$files = array();

// Hier wird $h ein „Handle“ zugewiesen. Das ist grob gesagt eine von PHP ver-
// waltete Ressourcenkennung, die nachfolgenden Funktionen Informationen über
// einen bestimmten Kontext zur Verfügung stellt. Gilles hat es in seiner Erklä-
// rung zu readdir bereits angesprochen: readdir durchläuft die Einträge eines
// Verzeichnisses nacheinander. Dazu muss die Funktion natürlich wissen, an wel-
// cher „Stelle“ sie sich im Verzeichnis befindet. Diese Angaben speichert PHP
// intern beim Handle. Ich weiß, das ist etwas vage, aber wesentlich genauer
// wird PHP bei sowas nicht. Ein passender Vergleich wäre etwa ein ResultSet
// einer Datenbankabfrage. Das wird auch der Reihe nach durchlaufen, ohne dass
// PHP konkrete Informationen bereitstellt, was die interne Umsetzung anbelangt.
// Von der Vorstellung her könnte man vielleicht sagen, dass sowas hardgecodete
// Objekte sind, die PHP intern nutzt, die aber dem Programmierer kein echtes
// Interface zur Verfügung stellen, sondern „Zugriff“ nur über ebenfalls interne
// Funktionen (hier etwa readdir) erlauben. Hervorzuheben ist dabei, dass diese
// Dinge nicht als Objekte mit Methoden angelegt sind (handle->read), sondern
// „prozedural“ (read(handle)). Das ist vermutlich der Tatsache geschuldet, dass
// viele PHP-Funktionen „Mappings“ zu C-Funktionen sind, die meist ohne Objekt-
// orientierung (sie sind „älter“) auskommen und Pointer auf bestimmte Daten-
// strukturen als Argumente erwarten. PHP abstrahiert da nicht immer großartig,
// sondern reicht manche Aufrufe strukturell einfach eins zu eins an die bereits
// vor der „Erfindung“ von PHP existierenden C-Funktionen weiter. Ganz pauschal
// könnte man möglicherweise behaupten, dass ein Handle oder eine Ressourcen-
// kennung ein C-Pointer ist, der nie in objektorientierten PHP-Code umgeformt
// wurde.
// Für die Verzeichnisklasse gibt es übrigens einen „echten“ OOP-Ansatz:
//   http://www.php.net/manual/en/class.dir.php
// Eine weitere moderne Impementation ist:
//   http://www.php.net/manual/de/recursivedirectoryiterator.construct.php
$h = opendir($dir);

// Wichtig ist hier die Nuance, dass readdir auf einer „Instanz“ eines Verzeich-
// nis-„Objekts“ arbeitet, auf das durch den Handle verwiesen wird. Modern wür-
// de man hier wohl etwas in der Richtung von $h->read() schreiben
while (($file = readdir($h)) !== false) {
    // Das hat Gilles bereits erklärt. In der Unix(?)-Welt enthält jedes Ver-
    // zeichnis die beiden „Dateien“ „.“ und „..“, die für „aktuelles Verzeich-
    // nis“ beziehungsweise „übergeordnetes Verzeichnis“ stehen. Der Zweck von
    // „..“ dürfte einzusehen sein. „.“ ist immer dann sinnvoll, wenn eine An-
    // wendung verschiedene Verzeichnisse nach einem angegebenen Pfad durchsuchen
    // würde. Ein gutes Beispiel dafür ist der Include-Pfad von PHP, auf dem
    // mehrere Verzeichnisse definiert werden können, die nacheinander nach
    // einer nachgefragten Datei durchsucht werden. Eine Angabe wie
    //   include 'file.php';
    // würde im ersten Verzeichnis des Include-Pfads nach „file.php“ suchen,
    // danach im zweiten und so weiter. Die Angabe
    //   include './file.php';
    // besagt hingegen, dass die nachgefragte Datei aus dem working directory
    // des ausgeführten Scripts eingebunden werden soll. Diese Angabe umgeht
    // den Include-Pfad. Das ist mitunter sinnvoll, um zu vermeiden, dass PHP
    // eine zufällig gleichnamige Datei einbindet, die in irgendeiner Bibliothek
    // enthalten ist, die sich auf dem Include-Pfade befindet
    if ($file === '.' || $file === '..') {
        continue;
    }

    $files[] = $file;
}

Gilles schrieb:
PHP:
    // Möglichkeit 2, welche ich bevorzuge wäre folgende
    // array_push($files, $file);

Du würdest Perl lieben. :)

- http://www.html.de/php/41047-erstellung-eines-spielplans.html#post298192
 
Werbung:
Danke mermshaus.
Das war noch mal ne Menge Lesestoff, den ich bestimmt noch ein zwei mal lesen werde, bevor ich mich zu der Annahme verleiten lasse, alles verstanden zu haben.
Auf jeden Fall sind schon mal ein paar Erkenntnisse dabei abgefallen, mit denen ich gar nicht gerechnet hatte.
 
Zurück
Oben