Dapatkan path absolut dari skrip yang awalnya dijalankan

247

Saya telah mencari tinggi dan rendah dan mendapatkan banyak solusi dan variabel yang berbeda yang berisi info untuk mendapatkan jalur absolut. Tetapi mereka tampaknya bekerja dalam beberapa kondisi dan tidak dalam kondisi lain. Apakah ada satu cara ampuh untuk mendapatkan path absolut dari skrip yang dieksekusi dalam PHP? Bagi saya, skrip akan dijalankan dari baris perintah, tetapi, solusi harus berfungsi sama baiknya jika dijalankan di dalam Apache dll.

Klarifikasi: Skrip yang awalnya dieksekusi, tidak harus berupa file tempat solusi dikodekan.

inquam
sumber
benar memang seperti matematika. Saya menerimanya sejak lama ketika saya hanya memiliki satu skrip dan itu berhasil untuk saya. Saya menghapus jawaban yang diterima untuk menjelaskan bahwa itu tidak menyelesaikan masalah awal. Menyimpan konstanta FILE ketika eksekusi dimulai dalam skrip adalah salah satu cara untuk pergi, tetapi jauh dari ideal.
inquam
skrip yang diminta adalah yang Anda inginkan, skrip saat ini = dengan kode solusi ini
Bitterblue

Jawaban:

33

Solusi yang benar adalah dengan menggunakan get_included_filesfungsi ini:

list($scriptPath) = get_included_files();

Ini akan memberi Anda jalan absolut dari skrip awal bahkan jika:

  • Fungsi ini ditempatkan di dalam file yang disertakan
  • Direktori kerja saat ini berbeda dari direktori skrip awal
  • Script dieksekusi dengan CLI, sebagai jalur relatif

Berikut ini dua skrip uji; skrip utama dan file yang disertakan:

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

Dan hasilnya; perhatikan direktori saat ini:

C:\>php C:\Users\Redacted\Desktop\main.php
The script being executed is C:\Users\Redacted\Desktop\main.php
Salman A
sumber
Solusi ini berfungsi tetapi perlu disebutkan bahwa, membaca dokumentasinya , tidak disebutkan bahwa path skrip yang awalnya dijalankan adalah item pertama dari array yang dikembalikan oleh get_included_files(). Saya menyarankan untuk menyimpan __FILE__konstanta di awal skrip yang seharusnya dijalankan.
Paolo
270

__FILE__ konstanta akan memberi Anda path absolut ke file saat ini.

Perbarui :

Pertanyaan diubah untuk menanyakan cara mengambil skrip yang awalnya dijalankan alih-alih skrip yang saat ini berjalan. Satu-satunya cara yang dapat diandalkan untuk melakukan itu adalah dengan menggunakan debug_backtracefungsi tersebut.

$stack = debug_backtrace();
$firstFrame = $stack[count($stack) - 1];
$initialFile = $firstFrame['file'];
zerkms
sumber
Jika saya menggunakan pola pengontrol depan. Apakah __FILE__mengembalikan lokasi index.php atau lokasi file yang disertakan? Bagaimana saya mendapatkan lokasi index.php?
CMCDragonkai
Baik __FILE__memang menunjuk ke jalur skrip saat ini. Tapi saya belum menemukan apa pun untuk menunjukkan jalur index.php saat ini.
CMCDragonkai
1
@ CMCDragonkai: ajukan pertanyaan yang terpisah
zerkms
2
PERHATIAN: jika skrip berada dalam direktori virtual apache2, informasi yang dikembalikan TIDAK memberikan lokasi jalur nyata di server fisik. Saya menginginkan ini untuk keperluan debug, dan bahkan variabel $ _SERVER tidak menyediakan ini. Misalnya, jika index.php ada di / var / www / vpath1 / html dan / var / www / html / dan / var / www / vpath2 / html, dan masing-masing ini hampir dipetakan ke / var / www / html, maka / var / www / html adalah apa yang akan Anda lihat, tidak peduli server virtual mana yang digunakan.
Mark Richards
1
@ChristofferBubach Anda bahkan tidak perlu membuangnya: objek pengecualian mengumpulkan jejak stack selama konstruksi.
zerkms
262

Jawaban telah dipindahkan di sini - https://stackoverflow.com/a/26944636/2377343

T.Todua
sumber
1
untuk mendapatkan folder skrip saat inistr_replace( basename(__FILE__) , '',str_replace($_SERVER["DOCUMENT_ROOT"],'',str_replace('\\','/',__FILE__ ) ) ) === /folder1/folder2/
Salem
2
Sejauh ini, ini adalah daftar contoh cara untuk mendapatkan sebagian atau semua jalur file yang paling komprehensif yang pernah saya lihat di seluruh internet.
Sean the Bean
241
echo realpath(dirname(__FILE__));

Jika Anda menempatkan ini dalam file yang disertakan, ia akan mencetak path ke ini termasuk. Untuk mendapatkan lintasan skrip induk, ganti __FILE__dengan $_SERVER['PHP_SELF']. Namun ketahuilah bahwa PHP_SELF adalah risiko keamanan!

rik
sumber
1
Ini persis apa yang saya inginkan
inquam
13
apa gunanya realpath di sini?
Akal Sehat Anda
11
@Col. Shrapnel: "Sejak PHP 4.0.2, __FILE__selalu berisi jalur absolut dengan symlink diselesaikan sementara di versi yang lebih lama berisi jalur relatif dalam beberapa keadaan." plus "dirname () beroperasi secara naif pada input string, dan tidak mengetahui filesystem yang sebenarnya, atau komponen path seperti '..'.
rik
6
oh, 4.0.2. Abad terakhir?
Akal Sehat Anda
2
@rik: juga, masalah keamanan apa yang dapat menyebabkan PHP_SELF??
zerkms
38
__DIR__

Dari manual :

Direktori file. Jika digunakan di dalam sebuah include, direktori file yang disertakan dikembalikan. Ini setara dengan dirname(__FILE__). Nama direktori ini tidak memiliki garis miring kecuali jika itu adalah direktori root.
__FILE__ selalu berisi path absolut dengan symlink yang diselesaikan sedangkan dalam versi yang lebih lama (dari 4.0.2) itu berisi path relatif dalam beberapa keadaan.

Catatan : __DIR__ditambahkan dalam PHP 5.3.0.

Gottlieb Notschnabel
sumber
21

Jika Anda ingin mendapatkan penggunaan direktori kerja saat inigetcwd()

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

__FILE__akan mengembalikan path dengan nama file misalnya pada XAMPP C:\xampp\htdocs\index.phpbukanC:\xampp\htdocs\

pkarecki
sumber
8
dirname(__FILE__) 

akan memberikan rute absolut dari file saat ini dari mana Anda menuntut rute, rute direktori server Anda.

contoh file:

www / http / html / index.php; jika Anda menempatkan kode ini di dalam index.php Anda akan kembali:

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

www / http / html / class / myclass.php; jika Anda menempatkan kode ini di dalam myclass.php Anda akan kembali:

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

Sultanos
sumber
7

Cukup gunakan di bawah ini:

echo __DIR__;
Matricore
sumber
1
Sry, idenya adalah untuk mendapatkan skrip dipecat pertama ... Bukan yang Anda kebetulan berada sekarang. Jadi pohon penyertaan a.php->b.php->c.phpharus menjadi jalur a.php jika dicentang di c.php . Satu-satunya cara yang tampaknya dapat diandalkan adalah dengan menggunakan fungsi debug_backtrace () .
inquam
5
`realpath(dirname(__FILE__))` 

itu memberi Anda skrip saat ini (skrip di mana Anda menempatkan kode ini) direktori tanpa trailing slash. ini penting jika Anda ingin menyertakan file lain dengan hasilnya

minhajul
sumber
Ya, tetapi idenya adalah untuk bisa mendapatkan jalur absolut ke "skrip tembak" A.php bahkan di dalam B.php jika itu dimasukkan oleh A.php. BISA atau tentu saja dilakukan dengan menyimpan skrip awal untuk akses nanti, tetapi pertanyaannya adalah apakah mungkin untuk mendapatkannya tanpa melakukan itu.
inquam
4

Jika Anda mencari jalur absolut relatif terhadap root server, saya telah menemukan bahwa ini berfungsi dengan baik:

$_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['SCRIPT_NAME'])
SiteKickr
sumber
Ketika saya memeriksa solusi ini terhadap server yang berbeda itu selalu memberi saya jalan dengan linux seperti pemisah dir terlepas dari OS host (Windows dan Linux). Bagi saya itu adalah keuntungan.
Bronek
3

Inilah fungsi PHP yang berguna yang saya tulis untuk ini dengan tepat. Saat pertanyaan awal mengklarifikasi, ia mengembalikan jalur dari mana skrip awal dieksekusi - bukan file tempat kita berada saat ini.

/**
 * 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
sumber
1

coba ini pada skrip Anda

echo getcwd() . "\n";
Shuhad zaman
sumber
1
realpath($_SERVER['SCRIPT_FILENAME'])

Untuk skrip yang dijalankan di bawah server web $_SERVER['SCRIPT_FILENAME']akan berisi path lengkap ke skrip yang awalnya disebut, jadi mungkin index.php Anda. realpath()tidak diperlukan dalam hal ini.

Untuk skrip, jalankan dari konsol $_SERVER['SCRIPT_FILENAME']akan berisi jalur relatif ke skrip awalnya Anda dipanggil dari dir Anda saat ini bekerja. Jadi, kecuali Anda mengubah direktori kerja di dalam skrip Anda, itu akan menyelesaikan ke jalur absolut.

Pemenang
sumber
1

Ini yang saya gunakan dan berfungsi di lingkungan Linux. Saya tidak berpikir ini akan bekerja pada mesin 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
sumber
1

Cara mudah untuk memiliki jalan yang mutlak dari naskah awalnya dieksekusi , dalam naskah dan script lainnya termasuk dengan include, require, require_onceadalah dengan menggunakan konstan dan menyimpan ada jalan naskah saat di awal dari script utama :

define( 'SCRIPT_ROOT', __FILE__ );

Solusi di atas cocok ketika ada satu "utama" skrip yang includesetiap skrip lain yang diperlukan, seperti di sebagian besar aplikasi web.

Jika bukan itu masalahnya dan mungkin ada beberapa "skrip intital" maka untuk menghindari redefinisi dan agar jalur yang benar disimpan di dalam konstanta setiap skrip dapat dimulai dengan:

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

Catatan tentang jawaban yang saat ini diterima :

jawabannya menyatakan bahwa jalur skrip yang awalnya dijalankan adalah elemen pertama dari array yang dikembalikan oleh get_included_files().

Ini adalah solusi yang cerdas dan sederhana dan -pada saat penulisan- (kita hampir menggunakan PHP 7.4.0) itu berhasil .

Namun dengan melihat dokumentasi tidak disebutkan bahwa skrip yang awalnya dieksekusi adalah item pertama dari array yang dikembalikan oleh get_included_files().

Kami hanya membaca

Script yang awalnya dipanggil dianggap sebagai "file yang disertakan," sehingga akan terdaftar bersama dengan file yang direferensikan oleh include dan keluarga.

Pada saat penulisan " skrip awalnya disebut " adalah yang pertama dalam array tetapi - secara teknis - tidak ada jaminan bahwa ini tidak akan berubah di masa depan.


Catatan tentang realpath(), __FILE__dan __DIR__:

Lain telah disarankan dalam jawaban mereka penggunaan __FILE__, __DIR__, dirname(__FILE__), realpath(__DIR__)...

dirname(__FILE__)sama dengan __DIR__(diperkenalkan dalam PHP 5.3.0), jadi gunakan saja __DIR__.

Keduanya __FILE__dan __DIR__selalu jalur absolut sehingga realpath()tidak perlu.

Paolo
sumber