Sind PHP-Include-Pfade relativ zur Datei oder zum aufrufenden Code?

110

Ich habe Probleme, den Regelsatz für PHP-relative Include-Pfade zu verstehen. Wenn ich die Datei A.PHP- ausführe und die Datei A.PHP die Datei B.PHP enthält, die die Datei C.PHP enthält, sollte der relative Pfad zu C.PHP in Bezug auf den Speicherort von B.PHP oder den Speicherort von A stehen .PHP? Das heißt, spielt es eine Rolle, aus welcher Datei das Include aufgerufen wird oder nur, was das aktuelle Arbeitsverzeichnis ist und was das aktuelle Arbeitsverzeichnis bestimmt?

Yarin
quelle
Genauere als akzeptierte Antwort meiner Meinung nach: stackoverflow.com/a/23902890/1636522 .
Blatt

Antworten:

131

Es ist relativ zum Hauptskript, in diesem Fall A.php. Denken Sie daran, dass include()nur Code in das aktuell ausgeführte Skript eingefügt wird.

Das heißt, spielt es eine Rolle, aus welcher Datei das Include aufgerufen wird

Nein.

Wenn Sie es wichtig machen und ein Include relativ zu B.php ausführen möchten, verwenden Sie die __FILE__Konstante (oder __DIR__seit PHP 5.2 IIRC), die immer auf die aktuelle Literaldatei verweist, in der sich die Codezeile befindet.

include(dirname(__FILE__)."/C.PHP");
Pekka
quelle
@ Pekka- super- genau das, wonach ich gesucht habe. Weitere Informationen finden Sie unter stackoverflow.com/questions/2184810/…
Yarin
7
Sie können auch __DIR__genau für diesen Zweck verwenden.
Nick Bedford
1
Diese Antwort ist etwas übertrieben: NO NEED include(dirname(__FILE__)."/C.PHP");, weil include("C.PHP");es ausreicht (Ja! C.PHP kann sich im selben Verzeichnis wie B.PHP befinden). Es kann nur fehlschlagen, wenn Ihr Projekt zwei C.PHP-Dateien enthält.
Johnny Wong
Um es klarer zu machen: Es ist relativ zu B.php und A.php, wenn im Include-Pfad kein Präfix "./" oder "../" vorhanden ist. Siehe meine Antwort unten.
Johnny Wong
21

@ Pekka hat mich dorthin gebracht, möchte aber nur mitteilen, was ich gelernt habe:

getcwd() Gibt das Verzeichnis zurück, in dem sich die Datei befindet, mit deren Ausführung Sie begonnen haben.

dirname(__FILE__) Gibt das Verzeichnis der Datei zurück, die den aktuell ausgeführten Code enthält.

Mit diesen beiden Funktionen können Sie jederzeit einen Include-Pfad relativ zu Ihren Anforderungen erstellen.

Wenn sich b.php und c.php ein Verzeichnis teilen, kann b.php c.php wie folgt enthalten:

include(dirname(__FILE__).'/c.php');

egal woher b.php gerufen wurde.

Tatsächlich ist dies die bevorzugte Methode zum Einrichten relativer Pfade, da der zusätzliche Code PHP davon befreit, beim Versuch, die Zieldatei zu finden, den include_path durchlaufen zu müssen.

Quellen:

Unterschied zwischen getcwd () und dirname (__ FILE__)? Welches soll ich verwenden?

Warum sollten Sie dirname (__ FILE__) verwenden?

Yarin
quelle
Ich möchte etwas hinzufügen, ich hatte eine Datei namens csb.php, enthielt eine Funktionsdatei aus einem Ordner und die Funktionsdatei enthielt eine Datei mit dem Namen t.php aus demselben Ordner wie die Funktionsdatei. Als ich versuchte, a einzuschließen Die Datei mit dem Namen csb.php aus dem Ordner t.php wurde gestartet und enthielt dieselbe csb.php, die auch die Funktionsdatei aufgerufen hat. Als ich jedoch die zweite csb.php in csbe.php änderte, funktionierte sie sofort. Es sieht also so aus, als würde der erste Ordner priorisiert, dann der zweite Include-Ordner!
Miguel Vieira
17
  1. Wenn der Include-Pfad nicht mit ./oder beginnt ../, z.

    include 'C.php'; // precedence: include_path (which include '.' at first),
                     // then path of current `.php` file (i.e. `B.php`), then `.`.
  2. Wenn der Include-Pfad mit ./oder beginnt ../, z.

    include './C.php';  // relative to '.'
    
    include '../C.php'; // also relative to '.'

Das .oder ..höher ist relativ zu getcwd(), wobei standardmäßig der Pfad der Eingabedatei .phpverwendet wird (d. H.A.php ) verwendet wird.

Getestet auf PHP 5.4.3 (Erstellungsdatum: 8. Mai 2012 00:47:34).

(Beachten Sie auch, dass chdir()dies die Ausgabe von ändern kann getcwd().)

Johnny Wong
quelle
Abschließend wird der Pfad von A.php zuerst nach C.php durchsucht, dann wird der Pfad von B.php durchsucht, wenn das Include kein Präfix './' oder '../' enthält. (Nehmen Sie die Standardeinstellung von PHP an)
Johnny Wong
Vielen Dank, dass Sie mich darauf hingewiesen haben chdir(__DIR__), das Problem mit zu beheben.
HartleySan
[...] getcwd(), der standardmäßig den Pfad der .php-Eintragsdatei [...] verwendet - nicht unbedingt wahr. Wenn ich PHP in der Befehlszeile ausführe, getcwd()verweist es auf das aktuelle Arbeitsverzeichnis der Shell, unabhängig davon, welche .phpDatei ich aufrufe. Ich kann mir jedoch vorstellen, dass, wenn PHP in einer Webserverumgebung ausgeführt wird, die Umgebung das aktuelle Arbeitsverzeichnis in der Eintragsdatei initialisiert .php. Getestet unter MacOS mit PHP 7.2.2 über Homebrew installiert.
Herzbube
16

Die akzeptierte Antwort von Pekka ist unvollständig und im Allgemeinen irreführend. Wenn die Datei als relativer Pfad bereitgestellt includewird, sucht das aufgerufene Sprachkonstrukt folgendermaßen danach.

Zunächst werden die Pfade der Umgebungsvariablen durchlaufen include_path, mit denen festgelegt werden kann ini_set. Wenn dies fehlschlägt, wird im eigenen Verzeichnis des aufrufenden Skripts gesucht dirname(__FILE__)( __DIR__mit php> = 5.3). Wenn dies ebenfalls fehlschlägt, wird nur dann im Arbeitsverzeichnis gesucht! Es stellt sich nur heraus, dass die Umgebungsvariable standardmäßig include_pathmit .dem aktuellen Arbeitsverzeichnis beginnt . Dies ist der einzige Grund, warum zuerst im aktuellen Arbeitsverzeichnis gesucht wird. Siehe http://php.net/manual/en/function.include.php .

Dateien werden basierend auf dem angegebenen Dateipfad oder, falls keiner angegeben ist, dem angegebenen include_path eingeschlossen. Wenn die Datei nicht im include_path gefunden wird, überprüft include schließlich das eigene Verzeichnis des aufrufenden Skripts und das aktuelle Arbeitsverzeichnis, bevor ein Fehler auftritt.

Die richtige Antwort auf den ersten Teil der Frage lautet also, dass es wichtig ist, wo sich das enthaltene aufrufende Skript befindet. Die Antwort auf den letzten Teil der Frage lautet, dass das anfängliche Arbeitsverzeichnis in einem Webserverkontext das Verzeichnis des aufgerufenen Skripts ist, das alle anderen enthält, während es von PHP verarbeitet wird. In einem Befehlszeilenkontext ist das anfängliche Arbeitsverzeichnis das, was auch immer es ist, wenn PHP an der Eingabeaufforderung aufgerufen wird, nicht unbedingt das Verzeichnis, in dem sich das aufgerufene Skript befindet. Das aktuelle Arbeitsverzeichnis kann jedoch zur Laufzeit mit der PHP-Funktion geändert werden chdir. Siehe http://php.net/manual/en/function.chdir.php .

Dieser Absatz wurde hinzugefügt, um andere Antworten zu kommentieren. Einige haben erwähnt, dass das Verlassen auf include_pathweniger robust ist und es daher vorzuziehen ist, vollständige Pfade wie ./pathoder zu verwenden __DIR__ . /path. Einige sagten sogar, dass .es nicht sicher ist , sich auf das Arbeitsverzeichnis selbst zu verlassen, da es geändert werden kann. Manchmal müssen Sie sich jedoch auf Umgebungswerte verlassen. Beispielsweise möchten Sie möglicherweise include_pathleer setzen, damit das Verzeichnis des aufrufenden Skripts der erste Ort ist, an dem gesucht wird, noch vor dem aktuellen Arbeitsverzeichnis. Der Code wurde möglicherweise bereits regelmäßig aus externen Quellen geschrieben und aktualisiert, und Sie möchten das Präfix nicht __DIR__jedes Mal neu einfügen, wenn der Code aktualisiert wird.


quelle
"Wenn dies fehlschlägt, wird im eigenen Verzeichnis des aufrufenden Skripts dirname(__FILE__) (__DIR__)mit php> = 5.3 gesucht .)" Sind Sie sicher? Wo ist es dokumentiert? Ich hoffe , Sie sind falsch, und PHP ist nicht zu verwenden __FILE__und __DIR__für diesen Zweck, denn das würde sofort brechen einschließlich „Geschwister“ Skripte von Symlink eine! : -o (Was hier auf meinem 7.1-Setup glücklicherweise gut zu funktionieren scheint.)
Sz.
6

Kurze Antwort: Es ist relativ zum Inclusive-Skript.

TFM erklärt es richtig:

Wenn die Datei nicht im include_path gefunden wird, überprüft include das Verzeichnis des aufrufenden Skripts und das aktuelle Arbeitsverzeichnis

Wenn also /app/main.php sagt, include("./inc.php")dass /app/inc.php gefunden wird .

Die ./ ist nicht unbedingt erforderlich, entfernt jedoch jegliche Abhängigkeit von include_path.

Ich würde mich nicht darauf verlassen, Include-Dateien im aktuellen Arbeitsverzeichnis zu finden, falls jemand sie ändert chdir().

Denis Howe
quelle
Wenn Sie die Zeichenfolge mit beginnen ./, überprüft sie zuerst das Verzeichnis des aufrufenden Skripts oder zuerst das aktuelle Arbeitsverzeichnis?
Pacerier
2
@Denis Howe Nein, Sie sind bereits vom aktuellen Arbeitsverzeichnis abhängig, wenn Ihr Include-Pfad mit beginnt ./. dh chdir ("/ app / other") wird include("./inc.php")fehlschlagen. Verwenden Sie include("inc.php")daher in diesem Fall die Sicherheit.
Johnny Wong
@Pacerier Wenn die Zeichenfolge mit ./ oder ../ beginnt, wird nur das aktuelle Arbeitsverzeichnis überprüft. (include_path und Verzeichnis des aufrufenden Skripts (B.php) werden beide ignoriert). Siehe meine Antwort für weitere Details.
Johnny Wong
-2
dir
-> a.php
-> c.php

- dir2 
-> b.php

Um ain aufzunehmen b, müssen Sieinclude("../a.php");

Um bin aufzunehmen c, müssen Sieinclude("dir2/b.php");

Olli
quelle
4
@ Olli- Sie verpassen den Punkt der Frage- Ich habe gefragt, wie relative Pfade bestimmt werden, wenn Includes verkettet werden.
Yarin