Получить абсолютный путь изначально запускаемого скрипта

247

Я искал максимум и минимум и получал множество различных решений и переменных, содержащих информацию, чтобы получить абсолютный путь. Но они, кажется, работают в одних условиях, а не в других. Есть ли один способ «серебряной пули» получить абсолютный путь к исполняемому скрипту в PHP? Для меня сценарий будет запускаться из командной строки, но решение должно работать так же хорошо, если оно выполняется в Apache и т. Д.

Уточнение. Первоначально выполняемый сценарий, не обязательно файл, в котором закодировано решение.

inquam
источник
правда, математические облака Я принял это давным-давно, когда у меня был только один сценарий, и он работал для меня. Я удалил принятый ответ, чтобы понять, что это не решает начальную проблему. Сохранение константы 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'];
zerkms
источник
Если я использую шаблон фронт-контроллера. Вернет ли __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

T.Todua
источник
1
получить текущую папку скриптаstr_replace( basename(__FILE__) , '',str_replace($_SERVER["DOCUMENT_ROOT"],'',str_replace('\\','/',__FILE__ ) ) ) === /folder1/folder2/
Салем
2
Это, безусловно, самый полный список примеров способов получить часть или весь путь к файлу, который я видел во всем Интернете.
Шон Боб
241
echo realpath(dirname(__FILE__));

Если вы поместите это во включаемый файл, он напечатает путь к этому включению. Чтобы получить путь к родительскому сценарию, замените его __FILE__на $_SERVER['PHP_SELF']. Но учтите, что PHP_SELF - это угроза безопасности!

рик
источник
1
Это было именно то, что я хотел
Inquam
13
какая польза от realpath здесь?
Ваш здравый смысл
11
@Col. Шрапнель: «Начиная с PHP 4.0.2, __FILE__всегда содержит абсолютный путь с разрешенными символическими ссылками, тогда как в более старых версиях он содержал относительный путь при некоторых обстоятельствах». plus "dirname () наивно работает с входной строкой и не знает о фактической файловой системе или компонентах пути, таких как '..'.
rik
6
о, 4.0.2. Прошлый век?
Ваш здравый смысл
2
@rik: также, что проблема безопасности может вызвать PHP_SELF??
zerkms
38
__DIR__

Из руководства :

Каталог файла. Если используется внутри включения, возвращается каталог включенного файла. Это эквивалентно dirname(__FILE__). Это имя каталога не имеет косой черты, если только оно не является корневым каталогом.
__FILE__ всегда содержит абсолютный путь с разрешенными символическими ссылками, тогда как в более старых версиях (чем 4.0.2) он содержал относительный путь при некоторых обстоятельствах.

Примечание : __DIR__было добавлено в PHP 5.3.0.

Готтлиб Нотшнабель
источник
21

Если вы хотите получить текущий рабочий каталог, используйтеgetcwd()

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

__FILE__вернет путь с именем файла, например, на XAMPP C:\xampp\htdocs\index.phpвместоC:\xampp\htdocs\

pkarecki
источник
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/

Sultanos
источник
7

Просто используйте ниже:

echo __DIR__;
Matricore
источник
1
Извините, идея в том, чтобы получить первый запущенный сценарий ... Не тот, в котором вы оказались сейчас. Таким образом, дерево включения a.php->b.php->c.phpдолжно быть путем a.php, если проверено в c.php . Единственный надежный способ - использовать функцию debug_backtrace () .
Inquam
5
`realpath(dirname(__FILE__))` 

он дает вам текущий каталог скриптов (скрипт, в котором вы разместили этот код) без косой черты. это важно, если вы хотите включить другие файлы с результатом

minhajul
источник
Да, но идея в том, чтобы иметь возможность получить абсолютный путь к «сценарию обстрела» A.php даже внутри B.php, если он включен в A.php. Конечно, это можно сделать, сохранив исходный скрипт для последующего доступа, но вопрос был в том, возможно ли получить его без этого.
Инквам
4

Если вы ищете абсолютный путь относительно корня сервера, я обнаружил, что это работает хорошо:

$_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['SCRIPT_NAME'])
SiteKickr
источник
Когда я проверял это решение на разных серверах, оно всегда указывало мне путь к 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;
}
blizzrdof77
источник
1

попробуйте это на вашем сценарии

echo getcwd() . "\n";
Шухад Заман
источник
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']);
}
andrewniesen
источник
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()необходимости.

Paolo
источник