Uzyskaj bezwzględną ścieżkę do początkowo uruchomionego skryptu

247

Szukałem wysoko i nisko i otrzymałem wiele różnych rozwiązań i zmiennych zawierających informacje, aby uzyskać absolutną ścieżkę. Ale wydają się działać pod pewnymi warunkami, a nie pod innymi. Czy istnieje jeden srebrny sposób, aby uzyskać bezwzględną ścieżkę do wykonanego skryptu w PHP? Dla mnie skrypt będzie działał z wiersza poleceń, ale rozwiązanie powinno działać równie dobrze, jeśli działa w Apache itp.

Wyjaśnienie: Początkowo wykonany skrypt, niekoniecznie plik, w którym kodowane jest rozwiązanie.

zapytanie
źródło
to prawda, mathheadinclouds. Zaakceptowałem go dawno temu, kiedy miałem tylko jeden scenariusz i zadziałało to dla mnie. Usunąłem zaakceptowaną odpowiedź, aby wyjaśnić, że nie rozwiązuje ona początkowego problemu. Przechowywanie stałej PLIKU, gdy wykonywanie rozpoczyna się w skrypcie, jest jedną z możliwości, ale daleką od ideału.
pytaj
żądany skrypt jest tym, czego chciałeś, bieżący skrypt = z tym kodem rozwiązania
Bitterblue

Odpowiedzi:

33

Prawidłowym rozwiązaniem jest użycie get_included_filesfunkcji:

list($scriptPath) = get_included_files();

To da ci bezwzględną ścieżkę początkowego skryptu, nawet jeśli:

  • Ta funkcja jest umieszczona w dołączonym pliku
  • Bieżący katalog roboczy różni się od katalogu początkowego skryptu
  • Skrypt jest wykonywany za pomocą CLI jako ścieżki względnej

Oto dwa skrypty testowe; główny skrypt i dołączony plik:

# 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;
}

I wynik; zwróć uwagę na bieżący katalog:

C:\>php C:\Users\Redacted\Desktop\main.php
The script being executed is C:\Users\Redacted\Desktop\main.php
Salman A.
źródło
To rozwiązanie działa, ale warto wspomnieć, że podczas czytania dokumentacji nie ma wzmianki, że początkowo uruchomiona ścieżka skryptu jest pierwszym elementem tablicy zwróconym przez get_included_files(). I sugerują, do sklepu __FILE__na stałym poziomie na początku skryptu ma być początkowo biec.
Paolo,
270

__FILE__ stała da absolutną ścieżkę do bieżącego pliku.

Aktualizacja :

Pytanie zostało zmienione, aby zapytać, jak odzyskać początkowo wykonany skrypt zamiast aktualnie działającego skryptu. Jedynym (??) niezawodnym sposobem na to jest użycie debug_backtracefunkcji.

$stack = debug_backtrace();
$firstFrame = $stack[count($stack) - 1];
$initialFile = $firstFrame['file'];
zerkms
źródło
Jeśli używam wzorca kontrolera przedniego. Czy __FILE__zwróci lokalizację pliku index.php lub lokalizację dołączonego pliku? Jak uzyskać lokalizację index.php?
CMCDragonkai
Dobrze __FILE__wskazuje na ścieżkę bieżącego skryptu. Ale nie znalazłem niczego, co pokazuje bieżącą ścieżkę index.php.
CMCDragonkai
1
@CMCDragonkai: zadaj osobne pytanie
zerkms
2
UWAGA: jeśli skrypt znajduje się w katalogu wirtualnym apache2, zwrócone informacje NIE podają rzeczywistej lokalizacji ścieżki na serwerze fizycznym. Chciałem tego do celów debugowania, a nawet zmienne $ _SERVER tego nie zapewniają. Na przykład, jeśli plik index.php istnieje w / var / www / vpath1 / html i / var / www / html / i / var / www / vpath2 / html, a każdy z nich jest praktycznie odwzorowany na / var / www / html, wtedy zobaczysz / var / www / html, bez względu na to, który serwer wirtualny jest używany.
Mark Richards
1
@ChristofferBubach nawet nie musisz go rzucać: obiekt wyjątku zbiera ślad stosu podczas budowy.
zerkms,
262

Odpowiedź została przeniesiona tutaj - https://stackoverflow.com/a/26944636/2377343

T.Todua
źródło
1
uzyskać aktualny folder skryptustr_replace( basename(__FILE__) , '',str_replace($_SERVER["DOCUMENT_ROOT"],'',str_replace('\\','/',__FILE__ ) ) ) === /folder1/folder2/
Salem
2
To zdecydowanie najbardziej wyczerpująca lista przykładów uzyskania części lub całości ścieżki pliku, którą widziałem w całym Internecie.
Sean the Bean
241
echo realpath(dirname(__FILE__));

Jeśli umieścisz to w dołączonym pliku, drukuje ścieżkę do tego dołączenia. Aby uzyskać ścieżkę skryptu dominującej, wymienić __FILE__z $_SERVER['PHP_SELF']. Pamiętaj jednak, że PHP_SELF stanowi zagrożenie bezpieczeństwa!

rik
źródło
1
Właśnie tego chciałem
zapytaj
13
jaki jest pożytek z realpath?
Twój zdrowy rozsądek
11
@Przełęcz. Shrapnel: „Od PHP 4.0.2 __FILE__zawsze zawiera bezwzględną ścieżkę z rozwiązanymi dowiązaniami symbolicznymi, podczas gdy w starszych wersjach zawierała ścieżkę względną w pewnych okolicznościach.” plus "dirname () działa naiwnie na łańcuch wejściowy i nie jest świadomy rzeczywistego systemu plików ani składników ścieżki, takich jak„ .. ”.
rik
6
och, 4.0.2. Ostatni wiek?
Twój zdrowy rozsądek
2
@rik: także, jaki problem bezpieczeństwa może powodować PHP_SELF?
zerkms 10.01.11
38
__DIR__

Z instrukcji :

Katalog pliku. Jeśli zostanie zastosowany w pliku include, zwrócony zostanie katalog dołączonego pliku. Jest to równoważne z dirname(__FILE__). Ta nazwa katalogu nie ma ukośnika końcowego, chyba że jest to katalog główny.
__FILE__ zawsze zawiera bezwzględną ścieżkę z rozwiązanymi dowiązaniami symbolicznymi, podczas gdy w starszych wersjach (niż 4.0.2) zawierała ścieżkę względną w pewnych okolicznościach.

Uwaga : __DIR__dodano w PHP 5.3.0.

Gottlieb Notschnabel
źródło
21

Jeśli chcesz uzyskać bieżący katalog roboczy użyjgetcwd()

http://php.net/manual/en/function.getcwd.php

__FILE__zwróci ścieżkę z nazwą pliku na przykład na XAMPP C:\xampp\htdocs\index.phpzamiastC:\xampp\htdocs\

pkarecki
źródło
8
dirname(__FILE__) 

poda bezwzględną trasę bieżącego pliku, z którego żądasz trasy, trasę katalogu na serwerze.

przykładowe pliki:

www / http / html / index.php; jeśli umieścisz ten kod w pliku index.php, zwróci:

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

www / http / html / class / myclass.php; jeśli umieścisz ten kod w pliku myclass.php, zwróci:

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

Sultanos
źródło
7

Po prostu użyj poniżej:

echo __DIR__;
Matricore
źródło
1
Sry, chodzi o to, żeby dostać pierwszy uruchomiony skrypt ... Nie ten, w którym się teraz znajdujesz. Więc drzewko włączenie a.php->b.php->c.phppowinna być ścieżka a.php jeśli sprawdzany w c.php . Jedynym sposobem, który wydaje się wiarygodny, jest użycie funkcji debug_backtrace () .
zapytanie
5
`realpath(dirname(__FILE__))` 

daje ci aktualny katalog skryptu (skrypt, w którym umieściłeś ten kod), bez ukośnika. jest to ważne, jeśli chcesz dołączyć inne pliki z wynikiem

minhajul
źródło
Tak, ale pomysł polega na tym, aby uzyskać absolutną ścieżkę do „skryptu odpalającego” A.php nawet wewnątrz B.php, jeśli jest to uwzględnione przez A.php. Można to oczywiście zrobić poprzez zapisanie początkowego skryptu do późniejszego dostępu, ale pytanie brzmiało, czy można go uzyskać bez robienia tego.
zapytanie
4

Jeśli szukasz ścieżki bezwzględnej względem katalogu głównego serwera, zauważyłem, że działa to dobrze:

$_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['SCRIPT_NAME'])
SiteKickr
źródło
Kiedy sprawdzałem to rozwiązanie na różnych serwerach, zawsze dawało mi to ścieżkę z linuksem jak separatory dir niezależnie od systemu operacyjnego hosta (Windows i Linux). Dla mnie to zaleta.
Bronek
3

Oto przydatna funkcja PHP, którą dokładnie dla tego napisałem. Jak wyjaśnia pierwotne pytanie, zwraca ścieżkę, z której wykonano skrypt początkowy - a nie plik, w którym obecnie się znajdujemy.

/**
 * 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;
}
blizzrdof77
źródło
1

spróbuj tego na swoim skrypcie

echo getcwd() . "\n";
Shuhad Zaman
źródło
1
realpath($_SERVER['SCRIPT_FILENAME'])

Dla skryptu uruchamianego pod serwerem WWW $_SERVER['SCRIPT_FILENAME']będzie zawierać pełną ścieżkę do początkowo nazywanego skryptu, więc prawdopodobnie twój index.php. realpath()nie jest wymagane w tym przypadku.

Skrypt uruchamiany z konsoli $_SERVER['SCRIPT_FILENAME']będzie zawierał ścieżkę względną do początkowo wywoływanego skryptu z bieżącego katalogu roboczego. Więc jeśli nie zmienisz katalogu roboczego w skrypcie, rozwiąże on ścieżkę bezwzględną.

Zwycięzca
źródło
1

Tego używam i działa w środowiskach Linux. Nie sądzę, aby działało to na komputerze z systemem 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']);
}
andrewniesen
źródło
1

Prostym sposobem, aby mieć absolutną ścieżkę początkowo wykonywanego skryptu , w tym skrypcie i każdego innego skryptu dołączona include, require, require_oncejest za pomocą stałej i przechowywanie tam bieżącą ścieżkę skryptu na początku głównego skryptu :

define( 'SCRIPT_ROOT', __FILE__ );

Powyższe rozwiązanie jest odpowiednie, gdy istnieje jeden „główny” skrypt, który includejest wszystkim innym potrzebnym skryptem, jak w większości aplikacji internetowych.

Jeśli tak nie jest i może istnieć kilka „skryptów początkowych”, aby uniknąć redefinicji i mieć prawidłową ścieżkę przechowywaną w stałej, każdy skrypt może zaczynać się od:

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

Uwaga na temat (obecnie) akceptowanej odpowiedzi :

odpowiedź stwierdza, że ​​początkowo wykonana ścieżka skryptu jest pierwszym elementem tablicy zwróconym przez get_included_files().

Jest to sprytne i proste rozwiązanie i - w momencie pisania - (jesteśmy prawie w PHP 7.4.0) działa .

Jednak patrząc na dokumentację nie ma wzmianki, że początkowo wykonany skrypt jest pierwszym elementem tablicy zwróconym przez get_included_files().

My tylko czytamy

Pierwotnie wywoływany skrypt jest uważany za „dołączony plik”, dlatego zostanie wymieniony wraz z plikami, do których odwołują się dołączenia i rodzina.

W momencie pisania „ skrypt pierwotnie nazwany ” jest pierwszym w tablicy, ale - technicznie rzecz biorąc - nie ma gwarancji, że nie zmieni się to w przyszłości.


Uwaga na temat realpath(), __FILE__oraz __DIR__:

Inni sugerowali w swoich odpowiedziach użycia __FILE__, __DIR__, dirname(__FILE__), realpath(__DIR__)...

dirname(__FILE__)jest równy __DIR__(wprowadzony w PHP 5.3.0), więc po prostu użyj __DIR__.

Zarówno __FILE__i __DIR__zawsze ścieżki bezwzględne więc realpath()nie jest konieczne.

Paolo
źródło