Gerd: include und file_exists

Moin,

warum wird die Datei

$datei = "/xxxx.php" mit include($datei)

korrekt eingefügt und bei der Abfrage

if (file_exists($datei))

nicht gefunden?

  1. Moin Gerd,

    warum wird die Datei

    $datei = "/xxxx.php" mit include($datei) korrekt eingefügt und bei der Abfrage if (file_exists($datei)) nicht gefunden?

    ist bei Dir ein include_path gesetzt? include benutzt diesen, file_exists schaut nur im Dateisystem nach.

    Viele Grüße
    Robert

    1. Hallo Gerd,

      ich stimme brav dem Robert zu. Schau mal bitte beim php nach der Funktion realpath ... das könntest Du verwenden, bevor Du file_exists aufrufst, denn dann hast Du den richtigen Pfad vom Dateisystem.

      Viel Erfolg, Hans

      Moin Gerd,

      warum wird die Datei

      $datei = "/xxxx.php" mit include($datei) korrekt eingefügt und bei der Abfrage if (file_exists($datei)) nicht gefunden?

      ist bei Dir ein include_path gesetzt? include benutzt diesen, file_exists schaut nur im Dateisystem nach.

      Viele Grüße
      Robert

      1. Hallo Gerd und Hans,

        Inhaltsverzeichnis:

        1. realpath ist nicht die Lösung
        2. stream-resolve-include-path
        3. require statt include
        4. fopen statt include/require

        realpath()

        Vorsicht, nach meiner Erkenntnis löst realpath() keine INCLUDE_PATH-Verweise auf, nur symbolische Links. Und es braucht Execute-Permission auf dem ganzen Pfad zur Datei, weil das unter Linux nötig ist zum Auslesen von Verzeichnisinhalten.

        stream-resolve-include-path()

        Ich habe das Problem noch nicht gehabt, aber ein kurzer Blick ins Handbuch zeigt stream-resolve-include-path() als mögliches Mittel der Wahl, um einen Datei über den Include-Path zu finden. Soweit ich die Userkommentare dort richtig lese, kann man auch Dateinamen wie "lib/functions.php" finden, wenn das Elternverzeichnis von lib im Includepfad steht. Wenn stream_resolve_include_path false zurückgibt, existiert die Datei im include_path nicht. Da der include_path typischerweise "." enthält (das aktuelle Verzeichnis), ist eine file_exists Abfrage danach nicht mehr nötig.

        require statt include?

        Die Frage ist dann aber: wofür wird die Abfrage gebraucht? Um eine Fehlermeldung auszugeben, wenn eine Include-Datei nicht existiert? In diesem Fall kann man eventuell statt include auch require verwenden. Existiert die Datei nicht, wirft require ab PHP 8 eine Error-Exception, die man mit try/catch fangen kann. Ein Userkommentar auf der require-Seite im PHP-Handbuch zeigt, wie es geht.

        fopen(..., ..., true)

        Unter der Voraussetzung, dass man die Datei nicht auf Existenz prüfen, sondern einlesen möchte, gibt es einen weiteren Weg. In der Beschreibung der Kerndirektiven in php.ini steht:

        include_path string
        Specifies a list of directories where the require, include, fopen(), file(), readfile() and file_get_contents() functions look for files. The format is like the system's PATH environment variable: a list of directories separated with a colon in Unix or semicolon in Windows.

        file_exists() ist nicht in der Liste der Funktionen enthalten, die den include_path verwenden. Man könnte aber eine der anderen Funktionen verwenden, z.B. fopen($datei, "r", true) (3. Parameter auf true bedeutet: verwende den Include Path), wenn man die Datei einlesen will. Wenn es nur um die Existenzprüfung geht, ist stream_resolve_include_path mit file_exists wohl die bessere Idee.

        Rolf

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

          mit

          stream-resolve-include-path()

          hat es funktioniert, danke!

  2. Moin,

    warum wird die Datei

    $datei = "/xxxx.php" mit include($datei)

    korrekt eingefügt und bei der Abfrage

    if (file_exists($datei))

    nicht gefunden?

    Mit dem führenden Slash („/“) fällt es mir sehr schwer das zu glauben, dann müsste Dein Skript nämlich auf dem Dateisystem-Root liegen.

    → Überprüfe bitte, was Du da getestet hast.

    Meintest Du vielleicht:

    ## Beim Ausführen in einem Terminal ist
    ## $_SERVER['DOCUMENT_ROOT'] nicht besetzt oder leer:
    if (
    		( ! array_key_exists( 'DOCUMENT_ROOT', $_SERVER ) )
    	or  $_SERVER['DOCUMENT_ROOT'] == '' 
    ) {
        $_SERVER['DOCUMENT_ROOT'] = '.';
    } 
    
    $datei = $_SERVER['DOCUMENT_ROOT'] . '/xxxx.php';
    # …
    
    
  3. Moin,

    warum wird die Datei

    $datei = "/xxxx.php" mit include($datei)

    korrekt eingefügt und bei der Abfrage

    if (file_exists($datei))

    nicht gefunden?

    (1) Hast Du ein TocTou-Problem?

    Falls Du die Datei erstellst, dann includest und sodann löschst benutze zum Erstellen entweder die Funktion tmpfile() oder tempnam().

    tmpfile() stellt Dir eine Ressource („Dateizeiger“, a.k.a. „FileHandler“) bereit, in die Du schreiben und aus der Du nach einem rewind() auch wieder lesen kannst. Beides macht man aus Performancegründen „eher sehr selten“ in einem Skript.

    tempnam() eine temporäre Datei. Nimm das, falls Du da wirklich PHP-Code zur Laufzeit generieren und durch das includen ausführen willst.

    Ach so. Bei tmpfile() kommt die Müllabfuhr wenn das Skript beendet oder die ressorce mit fclose() geschlossen wird. Nimmst Du tempnam() musst Du die selbst zum Wertstoffhof bringen (unlink()).

    (2) Falls das ein Rätsel ist:

    Die Datei wurde zwischenzeitlich gelöscht oder ist auf einem Dateisystem, welches zwischenzeitlich nicht mehr erreichbar ist.

  4. Lieber Gerd,

    $datei = "/xxxx.php" mit include($datei)
    

    Dein Pfad ist ein absoluter Pfad. Er beginnt mit dem Slash (/), was bedeutet, dass er auf dem Server das Wurzelverzeichnis beschreibt. Dort hat Dein PHP-Prozess in aller Regel nichts verloren, sondern sollte erst in dem Unterverzeichnis des Dateisystems hantieren dürfen, welches als DOCUMENT_ROOT eingestellt ist. Deswegen solltest Du prinzipiell den Pfad zur Datei anders angeben:

    $pfad = './ziel-script.php';
    

    Jetzt sollte man wissen, welches Verzeichnis Dein PHP-Script an dieser Stelle als das aktuelle Verzeichnis (also das mit dem Punkt referenzierte) versteht. Willst Du den Pfad von Deinem aktuellen PHP-Script aus referenzieren, könnte das z.B. so aussehen:

    $pfad = __DIR__.'/../includes/nav.inc.php';
    

    Die magische Konstante __DIR__ enthält den kompletten Pfad desjenigen Verzeichnisses, in dem das PHP-Script gespeichert ist, in dem diese Konstante verwendet wird. Mit den zwei Punkten im obigen Beispiel wechseln wir in das darüber liegende Verzeichnis, um dann in das dortige Unterverzeichnis „includes“ zu wechseln und dort die Datei „nav.inc.php“ zu adressieren.

    Lesetipp in unserem Wiki: Dateien mit include nachladen

    Vielleicht hilft Dir das schon weiter?

    Liebe Grüße

    Felix Riesterer