Отримайте абсолютний шлях початково запущеного сценарію


247

Я шукав високо і низько і отримую безліч різних рішень і змінних, що містять інформацію, щоб отримати абсолютний шлях. Але вони, здається, працюють в одних умовах, а не в інших. Чи є один спосіб срібло кулі отримати абсолютний шлях виконаного сценарію в PHP? Для мене сценарій буде працювати з командного рядка, але рішення має функціонувати так само добре, якщо він запускається в Apache і т.д.

Уточнення: Спочатку виконаний скрипт, не обов'язково файл, в якому рішення кодується.


справді дійсно математика включає. Я прийняв це дуже давно, коли у мене був лише один сценарій, і він працював на мене. Я видалив прийняту відповідь, щоб зрозуміти, що вона не вирішує початкову проблему. Збереження константи FILE при запуску виконання в сценарії - це один із способів, але далеко не ідеальний.
інка

запитуваний скрипт - це те, що ви хотіли, поточний скрипт = з цим кодом рішення
Bitterblue

Відповіді:


33

Правильним рішенням є використання get_included_filesфункції:

list($scriptPath) = get_included_files();

Це дасть вам абсолютний шлях початкового сценарію, навіть якщо:

  • Ця функція розміщується у включеному файлі
  • Поточний робочий каталог відрізняється від каталогу початкового сценарію
  • Сценарій виконується з CLI, як відносний шлях

Ось два тестові сценарії; головний скрипт та доданий файл:

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

І результат; зауважте поточний каталог:

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

Це рішення працює, але варто згадати, що, читаючи документацію , не згадується, що початково шлях запущеного сценарію є першим елементом масиву, який повертає get_included_files(). Я пропоную зберігати __FILE__константу на початку сценарію, який повинен був бути запущений спочатку.
Паоло

270

__FILE__ константа дасть вам абсолютний шлях до поточного файлу.

Оновлення :

Питання було змінено, щоб запитати, як отримати спочатку виконаний сценарій замість поточного сценарію. Єдиний (??) надійний спосіб зробити це - використовувати debug_backtraceфункцію.

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

Якщо я використовую схему переднього контролера. Буде чи __FILE__повернути розташування index.php або місце розташування додається файлу? Як мені отримати місцезнаходження index.php?
CMCDragonkai

Добре __FILE__вказує на поточний шлях сценарію. Але я нічого не знайшов, щоб показати поточний шлях index.php.
CMCDragonkai

1
@CMCDragonkai: тоді задайте окреме запитання
zerkms

2
ПОПЕРЕДЖЕННЯ: якщо скрипт знаходиться у віртуальному каталозі apache2, повернута інформація НЕ забезпечує реального розташування шляху на фізичному сервері. Я хотів цього для налагодження, і навіть змінні $ _SERVER цього не забезпечують. Наприклад, якщо index.php існує в / var / www / vpath1 / html та / var / www / html / та / var / www / vpath2 / html, і кожен з них практично відображається на / var / www / html, тоді / var / www / html - це те, що ви побачите, незалежно від того, який віртуальний сервер використовується.
Марк Річардс

1
@ChristofferBubach вам навіть не потрібно його кидати: об’єкт винятку збирає слід стека під час побудови.
zerkms

262

Відповідь переміщено сюди - https://stackoverflow.com/a/26944636/2377343


1
отримати поточну папку сценаріюstr_replace( basename(__FILE__) , '',str_replace($_SERVER["DOCUMENT_ROOT"],'',str_replace('\\','/',__FILE__ ) ) ) === /folder1/folder2/
Salem

2
Це на сьогодні найповніший список прикладів способів отримати частину або весь шлях до файлів, який я бачив у всьому Інтернеті.
Шон Бін

241
echo realpath(dirname(__FILE__));

Якщо розмістити це у включеному файлі, він друкує шлях до цього включення. Щоб отримати шлях до батьківського сценарію, замініть __FILE__на $_SERVER['PHP_SELF']. Але майте на увазі, що PHP_SELF - це ризик для безпеки!


1
Це було саме те, що я хотів
дізнайся

13
в чому тут користь від realpath?
Твій здоровий глузд

11
@Col. Шрапнель: "Оскільки PHP 4.0.2, __FILE__завжди містить абсолютний шлях із вирішеними символьними посиланнями, тоді як у старих версіях він за певних обставин містив відносний шлях". плюс "dirname () працює наївно у вхідному рядку і не знає про фактичну файлову систему або компоненти контуру, такі як" .. ".
Рік

6
о, 4.0.2. Минуле століття?
Твій здоровий глузд

2
@rik: також, що може призвести до проблеми безпеки PHP_SELF??
zerkms

38
__DIR__

З посібника :

Каталог файлу. Якщо використовується всередині include, каталог повернутого файлу повертається. Це еквівалентно dirname(__FILE__). У назви цього каталогу немає косої риски, якщо це не коренева директорія.
__FILE__ завжди містить абсолютний шлях із вирішеними символьними посиланнями, тоді як у старих версіях (ніж 4.0.2) він містив відносний шлях за певних обставин.

Примітка : __DIR__додано в PHP 5.3.0.



8
dirname(__FILE__) 

дасть абсолютний маршрут поточного файлу, з якого ви вимагаєте маршрут, маршрут вашого каталогу сервера.

приклади файлів:

www / http / html / index.php; якщо ви помістите цей код всередині свого index.php, він повернеться:

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

www / http / html / class / myclass.php; якщо ви помістите цей код всередині свого myclass.php, він повернеться:

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


7

Просто використовуйте нижче:

echo __DIR__;

1
Шри, ідея полягає в тому, щоб отримати перший звільнений сценарій ... Не той, у кого ви трапляєтеся зараз. Отже, деревом включення a.php->b.php->c.phpмає бути шлях a.php, якщо він позначений у c.php . Єдиний спосіб, який здається надійним, - це використовувати функцію debug_backtrace () .
інкамація

5
`realpath(dirname(__FILE__))` 

він дає вам поточний скрипт (сценарій, всередині якого ви розмістили цей код), каталог без косої риски. це важливо, якщо ви хочете включити інші результати з результатом


Так, але ідея полягає в тому, щоб мати можливість пройти абсолютний шлях до "сценарію стрільби" A.php навіть всередині B.php, якщо це включено A.php. Це МОЖЕ, або звичайно, зробити, зберігаючи початковий скрипт для подальшого доступу, але питання полягав у тому, чи можна його отримати, не роблячи цього.
інкамація

4

Якщо ви шукаєте абсолютний шлях відносно кореня сервера, я виявив, що це працює добре:

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

Коли я перевіряв це рішення на різних серверах, він завжди давав мені шлях до розділювачів Linux, як dir, незалежно від ОС хоста (Windows та Linux). Для мене це перевага.
Бронек

3

Ось корисна функція PHP, яку я написав саме для цього. Як уточнюється оригінальне запитання, він повертає шлях, з якого був виконаний початковий скрипт - не той файл, у якому ми зараз перебуваємо.

/**
 * 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'])

Для запуску сценарію під веб-сервером $_SERVER['SCRIPT_FILENAME']буде міститися повний шлях до початково названого скрипту, тому, ймовірно, ваш index.php.realpath()в цьому випадку не потрібно.

Для запуску сценарію з консолі $_SERVER['SCRIPT_FILENAME']буде міститися відносний шлях до початково названого сценарію від вашого поточного робочого режиму. Тому, якщо ви не змінили робочий каталог всередині свого сценарію, він вирішиться до абсолютного шляху.


1

Це те, що я використовую, і це працює в середовищах Linux. Я не думаю, що це буде працювати на машині 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

Простий спосіб встановити абсолютний шлях спочатку виконаного сценарію , у цей скрипт та будь-який інший скрипт включений із include, require- require_onceце використовувати константу та зберігати там поточний шлях сценарію на початку основного сценарію :

define( 'SCRIPT_ROOT', __FILE__ );

Наведене вище рішення підходить, коли є єдиний "основний" скрипт, який використовується для includeкожного іншого необхідного сценарію, як у більшості веб-додатків.

Якщо це не так, і може бути декілька "інтитальних скриптів", щоб уникнути переосмислення та правильного шляху, що зберігається всередині константи, кожен сценарій може починатися з:

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

Примітка про (на даний момент) прийняту відповідь :

у відповіді зазначено, що спочатку виконаний шлях сценарію є першим елементом масиву, повернутим get_included_files() .

Це розумне і просте рішення, і в час написання (ми майже на PHP 7.4.0) воно працює .

Однак, переглядаючи документацію , не згадується, що первісно виконаний скрипт є першим елементом масиву, який повертає get_included_files().

Ми лише читаємо

Спочатку викликаний скрипт вважається "включеним файлом", тому він буде перерахований разом з файлами, на які посилаються include та family.

На момент написання " первісно названий сценарій " є першим у масиві, але - технічно - немає гарантії, що це не зміниться в майбутньому.


Примітка про realpath(), __FILE__і __DIR__:

Інші припустили в своїх відповідях на використання __FILE__, __DIR__, dirname(__FILE__), realpath(__DIR__)...

dirname(__FILE__)дорівнює __DIR__(введено в PHP 5.3.0), тому просто використовуйте __DIR__.

І те, __FILE__і __DIR__завжди є абсолютними шляхами, тому realpath()зайве.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.