Ottieni il percorso assoluto dello script inizialmente eseguito


247

Ho cercato in alto e in basso e ho ottenuto molte soluzioni e variabili diverse contenenti informazioni per ottenere il percorso assoluto. Ma sembrano funzionare in alcune condizioni e non in altre. C'è un modo di proiettile d'argento per ottenere il percorso assoluto dello script eseguito in PHP? Per me, lo script verrà eseguito dalla riga di comando, ma una soluzione dovrebbe funzionare altrettanto bene se eseguita all'interno di Apache ecc.

Chiarimento: lo script inizialmente eseguito, non necessariamente il file in cui è codificata la soluzione.


vero vero incarico di matematica. L'ho accettato molto tempo fa quando avevo solo una sceneggiatura e ha funzionato per me. Ho rimosso la risposta accettata per chiarire che non risolve il problema iniziale. Memorizzare la costante FILE all'avvio dell'esecuzione in uno script è un modo per procedere, ma tutt'altro che ideale.
Inquam

script richiesto è quello che volevi, script corrente = con questo codice di soluzione
Bitterblue

Risposte:


33

La soluzione corretta è utilizzare la get_included_filesfunzione:

list($scriptPath) = get_included_files();

Questo ti darà il percorso assoluto dello script iniziale anche se:

  • Questa funzione è inserita in un file incluso
  • La directory di lavoro corrente è diversa dalla directory dello script iniziale
  • Lo script viene eseguito con l'interfaccia della riga di comando, come percorso relativo

Ecco due script di test; lo script principale e un file incluso:

# C:\Users\Redacted\Desktop\main.php
include __DIR__ . DIRECTORY_SEPARATOR . 'include.php';
echoScriptPath();

# C:\Users\Redacted\Desktop\include.php
function echoScriptPath() {
    list($scriptPath) = get_included_files();
    echo 'The script being executed is ' . $scriptPath;
}

E il risultato; notare la directory corrente:

C:\>php C:\Users\Redacted\Desktop\main.php
The script being executed is C:\Users\Redacted\Desktop\main.php

Questa soluzione funziona ma vale la pena ricordare che, leggendo la documentazione , non si fa menzione del fatto che il percorso dello script inizialmente eseguito è il primo elemento dell'array restituito da get_included_files(). Io suggerisco di memorizzare __FILE__in una costante all'inizio dello script pensato per essere eseguito inizialmente.
Paolo,

270

__FILE__ costante ti darà il percorso assoluto al file corrente.

Aggiornamento :

La domanda è stata cambiata per chiedere come recuperare lo script inizialmente eseguito anziché lo script attualmente in esecuzione. L'unico modo (??) affidabile per farlo è utilizzare la debug_backtracefunzione.

$stack = debug_backtrace();
$firstFrame = $stack[count($stack) - 1];
$initialFile = $firstFrame['file'];

Se sto usando un modello di controller frontale. Sarebbe __FILE__tornare posizione della index.php o la posizione del file incluso? Come posso ottenere la posizione di index.php?
CMCDragonkai,

Bene __FILE__indica il percorso della sceneggiatura corrente. Ma non ho trovato nulla per mostrare l'attuale percorso dell'indice.php.
CMCDragonkai,

1
@CMCDragonkai: fai una domanda separata allora
zerkms,

2
ATTENZIONE: se lo script si trova in una directory virtuale apache2, le informazioni restituite NON forniscono la posizione del percorso reale sul server fisico. Lo volevo per scopi di debug e anche le variabili $ _SERVER non lo forniscono. Ad esempio, se index.php esiste in / var / www / vpath1 / html e / var / www / html / e / var / www / vpath2 / html, e ciascuno di questi è virtualmente mappato su / var / www / html, allora / var / www / html è ciò che vedrai, indipendentemente dal server virtuale utilizzato.
Mark Richards,

1
@ChristofferBubach non devi nemmeno lanciarlo: un oggetto di eccezione raccoglie la traccia dello stack durante la costruzione.
zerkms,

262

La risposta è stata spostata qui - https://stackoverflow.com/a/26944636/2377343


1
per ottenere l'attuale cartella della sceneggiaturastr_replace( basename(__FILE__) , '',str_replace($_SERVER["DOCUMENT_ROOT"],'',str_replace('\\','/',__FILE__ ) ) ) === /folder1/folder2/
Salem,

2
Questo è di gran lunga l'elenco più completo di esempi di modi per ottenere parte o tutto il percorso del file che ho visto su Internet.
Sean the Bean,

241
echo realpath(dirname(__FILE__));

Se lo inserisci in un file incluso, stampa il percorso di questa inclusione. Per ottenere il percorso dello script principale, sostituirlo __FILE__con $_SERVER['PHP_SELF']. Ma tieni presente che PHP_SELF è un rischio per la sicurezza!


1
Era esattamente quello che volevo
inquam

13
a che serve qui realpath?
Il tuo buon senso

11
@Col. Shrapnel: "Dal momento che PHP 4.0.2, __FILE__contiene sempre un percorso assoluto con collegamenti simbolici risolti mentre nelle versioni precedenti conteneva un percorso relativo in alcune circostanze." plus "dirname () opera in modo ingenuo sulla stringa di input e non è a conoscenza del file system attuale o dei componenti del percorso come '..'.
rik

6
oh, 4.0.2. L'ultimo secolo?
Il tuo buon senso

2
@rik: inoltre, quale problema di sicurezza può causare PHP_SELF??
zerkms,

38
__DIR__

Dal manuale :

La directory del file. Se utilizzato all'interno di un'inclusione, viene restituita la directory del file incluso. Questo equivale a dirname(__FILE__). Questo nome di directory non ha una barra finale a meno che non sia la directory principale.
__FILE__ contiene sempre un percorso assoluto con collegamenti simbolici risolti mentre nelle versioni precedenti (rispetto alla 4.0.2) conteneva un percorso relativo in alcune circostanze.

Nota : è __DIR__stato aggiunto in PHP 5.3.0.



8
dirname(__FILE__) 

darà il percorso assoluto del file corrente da cui si richiede la route, la route della directory del server.

file di esempio:

www / http / html / index.php; se inserisci questo codice nel tuo index.php restituirà:

<?php echo dirname(__FILE__); // this will return: www/http/html/

www / http / html / class / myclass.php; se inserisci questo codice nel tuo myclass.php restituirà:

<?php echo dirname(__FILE__); // this will return: www/http/html/class/


7

Basta usare qui sotto:

echo __DIR__;

1
Sry, l'idea è quella di ottenere la prima sceneggiatura licenziata ... Non quella in cui ti trovi adesso. Quindi un albero di inclusione di a.php->b.php->c.phpdovrebbe essere il percorso di a.php se controllato in c.php . L'unico modo che sembra affidabile è utilizzare la funzione debug_backtrace () .
Inquam,

5
`realpath(dirname(__FILE__))` 

ti dà la directory dello script corrente (lo script all'interno del quale hai inserito questo codice) senza barra. questo è importante se si desidera includere altri file con il risultato


Sì, ma l'idea è quella di essere in grado di ottenere il percorso assoluto della "sceneggiatura" A.php anche all'interno di B.php se questo è incluso da A.php. Può o ovviamente essere fatto memorizzando lo script iniziale per un accesso successivo, ma la domanda era se fosse possibile ottenerlo senza farlo.
Inchiesta il

4

Se stai cercando il percorso assoluto relativo alla radice del server, ho scoperto che funziona bene:

$_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['SCRIPT_NAME'])

Quando stavo controllando questa soluzione su server diversi, mi ha sempre dato il percorso con i separatori dir di Linux come indipendentemente dal sistema operativo dell'host (Windows e Linux). Per me questo è un vantaggio.
Bronek,

3

Ecco un'utile funzione PHP che ho scritto proprio per questo. Come chiarisce la domanda originale, restituisce il percorso da cui è stato eseguito lo script iniziale , non il file in cui ci troviamo attualmente.

/**
 * Get the file path/dir from which a script/function was initially executed
 * 
 * @param bool $include_filename include/exclude filename in the return string
 * @return string
 */ 
function get_function_origin_path($include_filename = true) {
    $bt = debug_backtrace();
    array_shift($bt);
    if ( array_key_exists(0, $bt) && array_key_exists('file', $bt[0]) ) {
        $file_path = $bt[0]['file'];
        if ( $include_filename === false ) {
            $file_path = str_replace(basename($file_path), '', $file_path);
        }
    } else {
        $file_path = null;
    }
    return $file_path;
}


1
realpath($_SERVER['SCRIPT_FILENAME'])

Per lo script eseguito nel server Web $_SERVER['SCRIPT_FILENAME']conterrà il percorso completo dello script inizialmente chiamato, quindi probabilmente il tuo index.php.realpath()non è richiesto in questo caso.

Per lo script eseguito dalla console $_SERVER['SCRIPT_FILENAME']conterrà il percorso relativo allo script inizialmente chiamato dalla directory di lavoro corrente. Quindi, a meno che tu non abbia cambiato la directory di lavoro all'interno del tuo script, si risolverà nel percorso assoluto.


1

Questo è quello che uso e funziona in ambienti Linux. Non penso che funzionerebbe su un computer Windows ...

//define canonicalized absolute pathname for the script
if(substr($_SERVER['SCRIPT_NAME'],0,1) == DIRECTORY_SEPARATOR) {
    //does the script name start with the directory separator?
    //if so, the path is defined from root; may have symbolic references so still use realpath()
    $script = realpath($_SERVER['SCRIPT_NAME']);
} else {
    //otherwise prefix script name with the current working directory
    //and use realpath() to resolve symbolic references
    $script = realpath(getcwd() . DIRECTORY_SEPARATOR . $_SERVER['SCRIPT_NAME']);
}

1

Un modo semplice per avere il percorso assoluto della scrittura eseguita inizialmente , in quello script e qualsiasi altro script incluso con include, require, require_onceè quello di utilizzare una costante e archiviazione esiste il percorso dello script corrente iniziale del script principale :

define( 'SCRIPT_ROOT', __FILE__ );

La soluzione sopra è adatta quando esiste un singolo script "principale" che includeè ogni altro script necessario, come nella maggior parte delle applicazioni web.

In caso contrario e potrebbero esserci diversi "script iniziali", per evitare ridefinizioni e per memorizzare il percorso corretto all'interno della costante, ogni script può iniziare con:

if( ! defined( 'SCRIPT_ROOT' ) ) {
    define( 'SCRIPT_ROOT`, __FILE__ );
}

Una nota sulla risposta (attualmente) accettata :

la risposta afferma che il percorso di script inizialmente eseguito è il primo elemento dell'array restituito da get_included_files() .

Questa è una soluzione intelligente e semplice e, al momento della scrittura, (siamo quasi a PHP 7.4.0) funziona .

Tuttavia, guardando la documentazione non si fa menzione del fatto che lo script inizialmente eseguito è il primo elemento dell'array restituito da get_included_files().

Abbiamo solo letto

Lo script originariamente chiamato è considerato un "file incluso", quindi verrà elencato insieme ai file a cui fanno riferimento include e family.

Al momento in cui scrivo lo " script originariamente chiamato " è il primo dell'array ma - tecnicamente - non esiste alcuna garanzia che ciò non cambierà in futuro.


Una nota su realpath(), __FILE__e __DIR__:

Altri hanno suggerito nelle loro risposte l'uso di __FILE__, __DIR__, dirname(__FILE__), realpath(__DIR__)...

dirname(__FILE__)è uguale a __DIR__(introdotto in PHP 5.3.0), quindi basta usare __DIR__.

Entrambi __FILE__e __DIR__sono sempre percorsi assoluti quindi realpath()non è necessario.

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.