PHP include percorsi relativi al file o al codice chiamante?


110

Ho problemi a comprendere il set di regole relativo ai percorsi di inclusione relativi a PHP. Se eseguo il file A.PHP- e il file A.PHP include il file B.PHP che include il file C.PHP, il percorso relativo a C.PHP deve essere in relazione alla posizione di B.PHP o alla posizione di A .PHP? Cioè, ha importanza da quale file viene chiamato l'inclusione, o solo quale sia la directory di lavoro corrente e cosa determina la directory di lavoro corrente?


Risposta più accurata di quella accettata a mio parere: stackoverflow.com/a/23902890/1636522 .
foglia

Risposte:


132

È relativo allo script principale, in questo caso A.php. Ricorda che include()inserisce semplicemente il codice nello script attualmente in esecuzione.

Cioè, importa da quale file viene chiamato l'inclusione

No.

Se si vuole fare importa, e fare un include rispetto al b.php, utilizzare la __FILE__costante (o __DIR__da PHP 5.2 IIRC), che sarà sempre puntare al file corrente letterale che la riga di codice si trova in.

include(dirname(__FILE__)."/C.PHP");

@ Pekka- fantastico- proprio quello che stavo cercando. Per ulteriori informazioni, vedere stackoverflow.com/questions/2184810/...
Yarin

7
Puoi anche usare __DIR__per quello scopo esatto.
Nick Bedford

1
Questa risposta è un po 'eccessiva: NESSUN BISOGNO include(dirname(__FILE__)."/C.PHP");, perché include("C.PHP");è sufficiente (Sì! C.PHP può essere nella stessa directory di B.PHP) Potrebbe non riuscire solo quando ci sono due file C.PHP nel progetto.
Johnny Wong

Per renderlo più chiaro: è relativo sia a B.php che a A.php se senza il prefisso "./" o "../" nel percorso di inclusione. Vedi la mia risposta di seguito.
Johnny Wong

21

@Pekka mi ha portato lì, ma voglio solo condividere ciò che ho imparato:

getcwd() restituisce la directory in cui risiede il file che hai iniziato a eseguire.

dirname(__FILE__) restituisce la directory del file contenente il codice attualmente in esecuzione.

Usando queste due funzioni, puoi sempre costruire un percorso di inclusione relativo a ciò di cui hai bisogno.

ad esempio, se b.php e c.php condividono una directory, b.php può includere c.php come:

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

non importa da dove è stato chiamato b.php.

In effetti, questo è il modo preferito per stabilire percorsi relativi, poiché il codice aggiuntivo libera PHP dal dover iterare attraverso include_path nel tentativo di individuare il file di destinazione.

fonti:

Differenza tra getcwd () e dirname (__ FILE__)? Quale dovrei usare?

Perché dovresti usare dirname (__ FILE__)


Vorrei aggiungere qualcosa, avevo un file chiamato csb.php, includeva un file di funzioni da una cartella e il file di funzioni includeva un file chiamato t.php dalla stessa cartella del file di funzioni, Quando ho provato a includere un file chiamato csb.php dalla cartella t.php era, ha iniziato a includere lo stesso csb.php che chiamava il file delle funzioni, ma quando ho cambiato il secondo csb.php in csbe.php ha iniziato a funzionare immediatamente. Quindi, sembra che dia la priorità alla prima cartella, quindi alla seconda cartella di inclusione!
Miguel Vieira

17
  1. Se includi percorso non inizia con ./o ../, ad esempio:

    include 'C.php'; // precedence: include_path (which include '.' at first),
                     // then path of current `.php` file (i.e. `B.php`), then `.`.
    
  2. Se includi percorso inizia con ./o ../, ad esempio:

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

Il .o ..sopra è relativo a getcwd(), che per impostazione predefinita è il percorso del .phpfile di ingresso (cioè A.php).

Testato su PHP 5.4.3 (data build: 8 maggio 2012 00:47:34).

(Si noti inoltre che chdir()può modificare l'output di getcwd().)


Per concludere, il percorso di A.php viene prima cercato per C.php, quindi il percorso di B.php viene cercato se non ci sono prefissi "./" o "../" nell'inclusione. (Supponiamo l'impostazione predefinita di PHP)
Johnny Wong

Grazie per avermi suggerito di utilizzare chdir(__DIR__)per risolvere il problema.
HartleySan

[...] getcwd(), che ha come valore predefinito il percorso del file .php della voce [...] - non necessariamente vero. Se eseguo PHP sulla riga di comando, getcwd()fa riferimento alla directory di lavoro corrente della shell, indipendentemente dal .phpfile che invoco. Posso immaginare, tuttavia, che se PHP viene eseguito in un ambiente di server Web, l'ambiente inizializza la directory di lavoro corrente nel .phpfile di ingresso . Testato su macOS con PHP 7.2.2 installato tramite Homebrew.
herzbube

16

La risposta accettata di Pekka è incompleta e, in un contesto generale, fuorviante. Se il file viene fornito come percorso relativo, il costrutto del linguaggio chiamato lo includecercherà nel modo seguente.

Innanzitutto, passerà attraverso i percorsi della variabile d'ambiente include_path, che può essere impostata con ini_set. Se fallisce, cercherà nella directory dello script chiamante dirname(__FILE__)( __DIR__con php> = 5.3.) Se anche questo fallisce, solo allora cercherà nella directory di lavoro! Si scopre solo che, per impostazione predefinita, la variabile di ambiente include_pathinizia con ., che è la directory di lavoro corrente. Questo è l'unico motivo per cui cerca prima nella directory di lavoro corrente. Vedi http://php.net/manual/en/function.include.php .

I file vengono inclusi in base al percorso file fornito o, se non ne viene fornito nessuno, include_path specificato. Se il file non viene trovato in include_path, include infine il controllo nella directory dello script chiamante e nella directory di lavoro corrente prima di fallire.

Quindi, la risposta corretta alla prima parte della domanda è che è importante dove si trova lo script di chiamata incluso. La risposta all'ultima parte della domanda è che la directory di lavoro iniziale , in un contesto di web server, è la directory dello script chiamato, lo script che include tutti gli altri pur essendo gestito da PHP. In un contesto da riga di comando, la directory di lavoro iniziale è qualunque sia quando viene richiamato php al prompt, non necessariamente la directory in cui si trova lo script chiamato. La directory di lavoro corrente , tuttavia, può essere modificata in fase di esecuzione con la funzione PHP chdir. Vedi http://php.net/manual/en/function.chdir.php .

Questo paragrafo viene aggiunto per commentare altre risposte. Alcuni hanno affermato che fare affidamento su include_pathè meno robusto e quindi è preferibile utilizzare percorsi completi come ./patho __DIR__ . /path. Alcuni sono arrivati ​​a dire che fare affidamento sulla directory di lavoro .stessa non è sicuro, perché può essere modificato. Tuttavia, alcune volte, è necessario fare affidamento sui valori dell'ambiente. Ad esempio, potresti voler impostare include_pathvuoto, in modo che la directory dello script chiamante sia il primo posto in cui cercherà, anche prima della directory di lavoro corrente. Il codice potrebbe essere già scritto e aggiornato regolarmente da fonti esterne e non si desidera reinserire il prefisso __DIR__ogni volta che il codice viene aggiornato.


"se fallisce, cercherà nella directory dello script chiamante dirname(__FILE__) (__DIR__)con php> = 5.3.)" Sei sicuro? Dove è documentato? Spero che ti sbagli, e PHP non usa __FILE__e __DIR__per questo scopo, in quanto ciò interromperebbe prontamente l'inclusione di script "fratelli" da quelli con link simbolico ! Eeeek !!! (Che, fortunatamente, sembra funzionare bene qui, sulla mia configurazione 7.1.)
Sz.

6

Risposta breve: è relativo allo script incluso.

TFM lo spiega correttamente:

Se il file non viene trovato in include_path, include controllerà la directory dello script chiamante e la directory di lavoro corrente

Quindi, se /app/main.php dice include("./inc.php")che troverà /app/inc.php .

Il ./ non è strettamente necessario, ma rimuove qualsiasi dipendenza da include_path.

Non farei affidamento sulla ricerca di file include nella directory di lavoro corrente nel caso in cui qualcuno lo cambi con chdir().


Quindi, se inizi la stringa con ./, controlla prima la directory dello script chiamante o prima la directory di lavoro corrente?
Pacerier

2
@Denis Howe No, dipendi già dalla directory di lavoro corrente se il tuo percorso di inclusione inizia con ./. cioè chdir ("/ app / altro") include("./inc.php")fallirà. Quindi, usa include("inc.php")per essere sicuro in questo caso.
Johnny Wong

@Pacerier se la stringa inizia con ./ o ../, controlla solo la directory di lavoro corrente. (include_path e la directory dello script chiamante (B.php) vengono entrambi ignorati). Vedi la mia risposta per maggiori dettagli.
Johnny Wong

-2
dir
-> a.php
-> c.php

- dir2 
-> b.php

Per includere ain bè necessarioinclude("../a.php");

Per includere bin cè necessarioinclude("dir2/b.php");


4
@ Olli- stai perdendo il punto della domanda- stavo chiedendo come vengono determinati i percorsi relativi quando gli include sono concatenati.
Yarin
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.