Verzeichnisstruktur auslesen
Onkel Schnitzel
- php
Hallo,
ich stecke mal wieder in einer Sackgasse. Für mein Redaktionssystem möchte ich mir die Struktur meines Bilder-Verzeichnisses anzeigen lassen. Das mache ich erstmal so:
function get_dir($dir) {
$id = $_GET['id'];
$fp=opendir($dir);
while($ordner=readdir($fp)) {
if(is_dir("$dir/$ordner") && $ordner!="." && $ordner!="..") {
echo "<a href="neues_bild.php?verz=$ordner&id=$id"><img src="ordner.gif" alt="Ordner" border="0" /> ".$ordner."</a><br />";
}
}
closedir($fp);
}
if(isset($_GET['verz'])) {
$verz = $_GET['verz'];
get_dir("../Bilder/$verz");
}
else {
get_dir("../Bilder");
}
Ich bekomme jetzt die Ordner ($verz) des Hauptverzeichnisses angezeigt und kann mit mir mit get_dir("../Bilder/$verz") auch einen Ordner auswählen und mir wiederum seine Unterverzeichnisse (quasi $verz2) anzeigen lassen. Aber dann ist Schluss, tiefer kann ich nicht gehen, da dann praktisch die Funktion get_dir("../Bilder/$verz2") aufgerufen wird. Das haut natürlich nicht hin, weil es heißen müßte get_dir("../Bilder/$verz/$verz2"). Und so weiter und so fort, je nachdem, wieviele Verzeichnisse folgen.
Ich könnte natürlich davon ausgehen, dass es maximal vier Unterverzeichnisse gibt und dann für jedes Unterverzeichnis eine neue Funktion schreiben, aber das ist wohl kein besonders schöner Stil und ist mir auch zu unflexibel, weil ich ja nicht weiß, wieviele Unterverzeichnisse eventuell später dazukommen. Ich habs auch schon mit einer sich immer wieder selbst aufrufenden Funktion versucht, aber damit bin ich nun erst gar nicht zurecht gekommen. Oder ist das der einzige Weg? Ich hoffe, ich konnte mich halbwegs verständlich ausdrücken.
Danke schonmal für eure Anregungen,
Onkel Schnitzel
Es geht wohl tatsächlich nur rekursiv. Hab jetzt n paar Beiträge dazu gefunden und werde mich mal versuchen, da durchzuwurschteln.
Bis denn,
Onkel Schnitzel
Lieber Schnitzel-Onkel,
ich verwende jetzt schon seit geraumer Weile eine Funktion, die ich mir aus den User-Comments auf PHP.net abgeschaut habe. Hier meine Version:
/* Funktion für Verzeichnisbaum
@$pfad: relativer Pfad; relativ zum $_SERVER['SCRIPT_SELF']
@$modus: (verzeichnisse|dateien|default)
@$rekursiv: Unterverzeichnisse auch? (true|false) */
function verzeichnis_inhalt($pfad, $modus = 'alle', $rekursiv = true) {
$pfad = preg_replace('~^(.*)/$~', '\\1', $pfad); // letzten Slash entfernen
$inhalt = array();
$zugriff = opendir($pfad);
while ($eintrag = readdir($zugriff)) {
if (!preg_match('~^\.\.?$~',$eintrag)) {
switch ($modus) {
case 'verzeichnisse':
if (is_dir("$pfad/$eintrag"))
$inhalt[] = "$pfad/$eintrag";
break;
case 'dateien':
if (is_file("$pfad/$eintrag"))
$inhalt[] = "$pfad/$eintrag";
break;
default:
$inhalt[] = "$pfad/$eintrag";
}
if ($rekursiv && is_dir("$pfad/$eintrag")) {
$inhalt2 = verzeichnis_inhalt("$pfad/$eintrag", $modus, $rekursiv);
foreach ($inhalt2 as $eintrag2)
$inhalt[] = $eintrag2;
}
}
}
closedir($zugriff);
return $inhalt;
}
Liebe Grüße aus Ellwangen,
Felix Riesterer.
Lieber Schnitzel-Onkel,
ich verwende jetzt schon seit geraumer Weile eine Funktion, die ich mir aus den User-Comments auf PHP.net abgeschaut habe. Hier meine Version:
Danke Lieber Riesterer-Felix,
ich werde mal versuchen, das für meine Zwecke anzupassen. Ich hab jetzt ne halbe Stunde draufgestarrt und langsam fang ich an, es halbwegs zu verstehen. :-)
Gruß,
Onkel Schnitzel
ich werde mal versuchen, das für meine Zwecke anzupassen.
Momentan versuche ich erst einmal zu gucken, was überhaupt im Array $inhalt steht, aber ich bekomme die Meldung 'Undefined vaiable $inhalt'. Ich kann aber den Fehler nicht finden.
function verzeichnis_inhalt($pfad) {
$pfad = preg_replace('~^(.*)/$~', '\1', $pfad); // letzten Slash entfernen
$inhalt = array();
$zugriff = opendir($pfad);
while ($eintrag = readdir($zugriff)) {
if (!preg_match('~^..?$~',$eintrag)) {
if (is_dir("$pfad/$eintrag")) {
$inhalt[] = "$pfad/$eintrag";
}
if (is_dir("$pfad/$eintrag")) {
$inhalt2 = verzeichnis_inhalt("$pfad/$eintrag");
foreach ($inhalt2 as $eintrag2)
$inhalt[] = $eintrag2;
}
}
}
closedir($zugriff);
return $inhalt;
}
verzeichnis_inhalt("../Bilder/");
print_r($inhalt);
Beste Grüße,
Onkel Schnitzel
Lieber Onkel Schnitzel,
verzeichnis_inhalt("../Bilder/");
was soll hier passieren?
print_r($inhalt);
Woher soll die Variable $inhalt kommen? Falls Du jetzt sagst "aus der Funktion wird doch $inhalt zurückgegeben", muss ich Dir widersprechen. Die Funktion gibt ein Array zurück, keinesfalls aber eine Variable. Daher spricht man ja auch vom Rückgabe_wert_ einer Funktion. Diesen musst Du aber erst einer Variablen zuweisen, um ihn weiter benutzen zu können: $wert = eine_funktion($eventuelle_parameter);
Übrigens: Die Variable $inhalt innerhalb der Funktion ist nur dort bekannt. Außerhalb der Funktion ist sie das nicht. Ebenso ist innerhalb der Funktion auch keine Variable verfügbar, die außerhalb von ihr definiert wurde (außer sogenannte globale oder superglobale Variablen)!
Vergleiche:
$inhalt = "außen";
echo $inhalt;
function test() {
$inhalt = "innen";
echo $inhalt;
}
test();
echo $inhalt;
Dein Problem ist gelöst, wenn Du folgendes notierst:
$inhalt = verzeichnis_inhalt("../Bilder/");
print_r($inhalt);
Liebe Grüße aus Ellwangen,
Felix Riesterer.
Aah, danke für die Aufklärung. Ich bin wirklich nicht gerade ein Programmierkönig. Für das Nötigste hats bis jetzt gereicht, aber bei dieser rekursiven Sache stoße ich an meine Grenzen.
Ich bekomme jetzt das Arry angezeigt.
[0] => ../Bilder/wappen
[1] => ../Bilder/Spielerfotos
[2] => ../Bilder/Spielerfotos/Berger
[3] => ../Bilder/Spielerfotos/Becker
...
Aber ehrlich gesagt, weiß ich gar nicht, was mir das konkret nützt. Es wird einfach nur alles hintereinander aufgelistet, so wie ichs auch ohne Array schon geschafft habe. Ich hatte eigentlich gedacht, das Array hilft mir irgendwie, die einzelnen Hierarchien abzuspeichern. Hmm, das Thema wird mich wohl noch ne Weile beschäftigen.
Beste Grüße,
Onkel Schnitzel
Lieber Onkel Schnitzel,
Ich bekomme jetzt das Arry angezeigt.
[0] => ../Bilder/wappen
[1] => ../Bilder/Spielerfotos
[2] => ../Bilder/Spielerfotos/Berger
[3] => ../Bilder/Spielerfotos/Becker
...
na also! Mission accomplished?
Aber ehrlich gesagt, weiß ich gar nicht, was mir das konkret nützt.
Holla! Was wolltest Du denn überhaupt erreichen?
Ich hatte eigentlich gedacht, das Array hilft mir irgendwie, die einzelnen Hierarchien abzuspeichern.
Du kannst einen String anhand eines Trennzeichens in ein Array umwandeln lassen? Die Funktion explode() hilft Dir dabei. Wenn man in einer Schleife
explode('/', $inhalt[$i]);
verwendet, so ergibt das je nach $i folgendes:
[$i=0] => Array(
'../',
'Bilder',
'wappen'),
[$i=1] => Array(
'../',
'Bilder',
'Spielerfotos'),
...
Klar soweit? Ok. Was uns das jetzt wiederum nützt? Na, jetzt bauen wir das um! Mit einer weiteren Schleife bauen wir aus
Array('../', 'Bilder', 'wappen')
eine völlig neue Struktur wie diese hier:
Array(
'../' => Array(
'Bilder' => Array(
'wappen')
)
)
Wird's jetzt klarer? Es hat schon eine hierarchische Struktur! Jetzt brauchen wir nur noch die anderen Einträge aus unserer Verzeichnisfunktion auf dieselbe Art behandeln, und wir haben jede Menge hierarchischer Arrays (in diesem Fall sogenannte "assoziative" Arrays, da der Index keine Zahl, sondern ein String wie '../' ist), die alle einen Teil einer Verzeichnis-Hierarchie darstellen.
Jetzt muss man nur noch die Arrays miteinander verschmelzen, sodass die Arrays mit gleichen Indices "zusammenwachsen". Dazu hilft Dir array_merge_recursive().
Aus diesen beiden Arrays wird ein einziges Array:
Array(
'../' => Array(
'Bilder' => Array(
'Spielerfotos' => Array(
'Becker')
)
)
Array(
'../' => Array(
'Bilder' => Array(
'Spielerfotos' => Array(
'Berger')
)
)
---------------- array_merge_recursive (in einer Schleife eingebaut! ------
Array(
'../' => Array(
'Bilder' => Array(
'Spielerfotos' => Array(
'Becker' => Array(),
'Berger' => Array()
),
)
)
)
Hmm, das Thema wird mich wohl noch ne Weile beschäftigen.
... und Du wirst 'ne Riesenmenge dabei über Arrays lernen (wahrscheinlich so, wie ich auch)!
Liebe Grüße aus Ellwangen,
Felix Riesterer.
Hallo Felix,
riesengroßen Dank für deine Mühe! Ich konnts jetzt zwar nur kurz überfliegen, aber morgen werd ich mich da reinknien und versuchen, es zu verstehen. Freu mich schon richtig drauf...
Beste Grüße,
Onkel Schnitzel