Gerrit: Abfrage ob Dir vorhanden

Hallo,
um abzufragen, ob ein directory vorhanden ist, habe ich zwei Versionen gefunden.
Welche ist besser geeignet?

if (@is_dir ($_SERVER['Aktuelles']))   {
   require_once ($_SERVER['Aktuelles'] . '/meta_ind.php');
    ......
}

oder

if (@opendir   ($_SERVER['Aktuelles']))  {
   require_once ($_SERVER['Aktuelles'] . '/meta_ind.php');
    ......
 }
  1. n'Abend,

    Welche ist besser geeignet?

    if (@is_dir ($_SERVER['Aktuelles']))   {
       require_once ($_SERVER['Aktuelles'] . '/meta_ind.php');
        ......
    }
    

    oder

    if (@opendir   ($_SERVER['Aktuelles']))  {
       require_once ($_SERVER['Aktuelles'] . '/meta_ind.php');
        ......
     }
    

    wie so oft im Leben: Es kommt drauf an. 🤭

    Wenn du nur einfach wissen musst, ob das Verzeichnis existiert, aber sonst nichts weiter damit anstellst, halte ich is_dir() für besser, weil die Funktion wirklich nur abfragt, ob das Filesystem-Objekt ein Verzeichnis ist (wenn es denn überhaupt existiert).

    Wenn du aber im Nachgang noch das Verzeichnis durchsuchen musst, ist opendir() als erster Schritt sinnvoll. Bedenke, dass opendir() das Verzeichnis im Erfolgsfall gleich zum Lesen öffnet und ein Handle dafür belegt, das man später mit closedir() wieder freigeben sollte.

    Einen schönen Tag noch
     Martin

    --
    Wichtige Erkenntnis für Comiczeichner:
    Eine Sprechblase ist nicht unbedingt ein Fall für den Urologen.
    1. Hallo Martin,

      wenn das Verzeichnis vorhanden ist, dann ist auch die mit require_once eingefügte Datei vorhanden.

      Mehr wird mit dem Verzeichnis nicht gemacht.

      Demnach ist wohl is_dir geeigneter (und schneller)?

      Gruß

      Gerrit

    2. Hallo,

      geht eigentlich flock() auch für Verzeichnisse?

      LG
      Mitleser 3einhalb

      1. Hi there,

        geht eigentlich flock() auch für Verzeichnisse?

        Afaik (und nach Nachschau im Manual) sperrt flock nur Ressourcen, die mit fopen() geöffnet werden können. Also, eher nein...

        1. Hallo klawischnigg,

          das hat mich jetzt interessiert. Man kann Verzeichnisse mit fopen zum Lesen öffnen. Sagt jemand bei Stackoverflow, und die entsprechende man-Page sagt was von einem Error, den man bekommt, wenn man ein Verzeichnis zu schreiben öffnen will.

          Unter Windows geht das allerdings nicht, da bekomme ich von fopen auf die Fingerchen, wenn ich es auf ein Verzeichnis loslasse. Unter Linux kann ich das gerade nicht testen.

          Was auch immer - flock ist für die Abfrage, ob ein Verzeichnis existiert, nicht der richtige Weg. Vor allem nicht, weil man vorher den fopen machen muss, das ist viel zu aufwändig.

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Hi there,

            das hat mich jetzt interessiert. Man kann Verzeichnisse mit fopen zum Lesen öffnen.

            In der Tat. Ich hab das nicht gewußt und ausprobiert (PHP 8.2), alleine, es ist, soweit ich gesehen habe, völlig nutzlos.

            Erstens ist ohnehin nur ein fopen(RESSOURCE,'r') möglich und zweitens liefert auch das nichts zurück. Ich habs zumindest mit fgets() probiert und da kamen keine Dateien oder irgendetwas 'raus. Nur die Fehlermeldung "Read of 8192 Bytes failed [...] is a direcory in...". Das einzige was Du da beim Öffnen mit fopen() bekommst ist ein Handle, mit dem Du nichts anfangen kannst. Ein (vermutlich genauso nutzloses) flock() allerdings gibt unabhängig von geshared oder exklusiv ein "true" zurück (auch wenn ich es von verschiedenen Clients aus gleichzeitig aufrufe.😉)

            Vielleicht gibts ja irgendeine sophisticated Anwendung, die ich mir jetzt nicht vorstellen kann, aber generell schaut mir das eher nach Bug als nach Feature aus...

  2. Hallo Gerrit,

    +1 an Martin für den Hinweis auf das Handle, das opendir erzeugt.

    Da Du den Verzeichnisinhalt nicht einlesen willst, ist is_dir aus meiner Sicht die bessere Idee. Die Funktion prüft, ob das angegebene Dateisystemobjekt existiert und ob es ein Verzeichnis ist.

    Die anderen Fragen, die sich stellen, sind:

    • Warum verwendest Du den @ Operator? Er unterdrückt Fehlermeldungen. Aber welche Fehlermeldung soll hier kommen? Die Doku sagt: "upon failure, an E_WARNING is emitted". Im Produktionsbetrieb gibst Du Warnungen eh nicht aus. @ überflüssig. Im Testbetrieb möchtest Du aber sehen, ob es Warnungen gibt und sie abstellen. @ überflüssig. Was könnte eine "failure" auslösen? Höchstens ein Wert in $_SERVER['Aktuelles'], der sich nicht als Pfad zu einem Ordner deuten lässt. Und das führt zur zweiten Frage:
    • Woher bekommt $_SERVER['Aktuelles'] seinen Wert? Du kannst im Apache mit SetEnv Aktuelles einen Wert zuweisen - aber das ist dann ein Wert, den Du unter Kontrolle hast und der keinen Fehler in is_dir auslösen sollte.

    Rolf

    --
    sumpsi - posui - obstruxi
      • Woher bekommt $_SERVER['Aktuelles'] seinen Wert? Du kannst im Apache mit SetEnv Aktuelles einen Wert zuweisen - aber das ist dann ein Wert, den Du unter Kontrolle hast und der keinen Fehler in is_dir auslösen sollte.

      Ich möchte in verschiedenen Anwendungen möglichst gleiche Komponenten verwenden. Daher kann es sein, dass im Projekt A das Verzeichnis definiert ist, im Projekt B aber nicht

      Gruß Gerrit

  3. Lieber Gerrit,

    if (@is_dir ($_SERVER['Aktuelles']))   {
       require_once ($_SERVER['Aktuelles'] . '/meta_ind.php');
        ......
    }
    

    mir scheint, dass Du über die superglobale Variable $_SERVER einen Wert für die unterschiedlichsten Teilprogramme bereitstellen willst, die dann mittels require_once() nachgeladen werden.

    besser: Konstanten verwenden

    Wahrscheinlich waren die meisten von uns auch schon einmal an dieser Stelle, auf unserem langen Weg das Schreiben von Webanwendungen zu erlernen. Kurz: Tu das bitte nicht!

    Wenn Du global gültige Variablen verwenden möchtest, dann greife auf sogenannte Konstanten zurück. Nach alter Programmierer-Tradition schreibt man Konstanten rein in Großbuchstaben, damit man auf den ersten Blick sieht, dass es sich um eine solche handelt:

    define('QUELLEN', '/var/www/mein/unterverzeichnis/quellen');
    
    if (is_dir(QUELLEN.'/Aktuelles')) {
      require_once (QUELLEN.'/Aktuelles/ind.php');
    }
    

    Der weitere Vorteil von Konstanten ist, dass sie nach ihrer Definition nicht mehr geändert werden können. In $_SERVER['irgendwas'] kann jeder Programmteil von irgendwoher irgendwelche Werte schreiben. Besonders dann, wenn Du fremde Programmteile mitverwendest (Bibliotheken für diverse Aufgaben wie z.B. Formulareingaben per Mail an Dich versenden), möchtest Du, dass die Werte, von denen Du Dein Programm abhängig machst, auch wirklich vertrauenswürdig sind.

    Wenn Du uns zeigen magst, was Du wirklich erreichen willst, können wir Dir sicher noch besseren Rat geben.

    Liebe Grüße

    Felix Riesterer

    1. Hallo Felix,

      $_SERVER['irgendwas']

      lässt sich über die .htaccess setzen, soweit ich weiß.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Lieber Rolf,

        $_SERVER['irgendwas']

        lässt sich über die .htaccess setzen, soweit ich weiß.

        das kann alles jederzeit zur Laufzeit in diesem PHP-Thread überschrieben werden. Das $_SERVER-Array ist keinesfalls readonly oder sonstwie schreibgeschützt, sondern ein ganz herkömmliches Array, dessen Schlüssel und Werte beim Aufruf des PHP-Scripts bestenfalls Anfangswerte darstellen.

        Liebe Grüße

        Felix Riesterer