获取初始运行脚本的绝对路径


247

我搜索了很多内容,并获得了很多不同的解决方案和包含信息的变量来获取绝对路径。但是它们似乎在某些条件下工作,而不在其他条件下工作。有没有一种方法可以获取PHP中已执行脚本的绝对路径?对我来说,该脚本将从命令行运行,但是,如果在Apache等内部运行,则解决方案也应起作用。

说明:最初执行的脚本,不一定是解决方案的编码文件。


确实是mathheadinclouds。很久以前,当我只有一个脚本并且对我有用时,我接受了它。我删除了可接受的答案,以明确说明它不能解决最初的问题。在脚本中开始执行时存储FILE常量是一种可行的方法,但并不理想。
2014年

请求的脚本就是您想要的,当前脚本=具有此解决方案代码
Bitterblue

Answers:


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__在最初要运行的脚本开头存储一个常量。
Paolo

270

__FILE__ 常量将为您提供当前文件的绝对路径。

更新

问题被更改为询问如何检索最初执行的脚本而不是当前正在运行的脚本。唯一可靠的方法是使用该debug_backtrace功能。

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

如果我使用前端控制器模式。是否将__FILE__返回index.php的位置或包含的文件的位置?我如何获得index.php的位置?
CMCDragonkai 2013年

那么__FILE__确实点到当前脚本的路径。但是我还没有发现任何可以显示当前index.php路径的东西。
CMCDragonkai 2013年

1
@CMCDragonkai:然后再问一个问题
zerkms,2013年

2
注意:如果脚本位于apache2虚拟目录中,则返回的信息不会提供物理服务器上的真实路径位置。我想要此用于调试目的,甚至$ _SERVER变量也不提供此功能。例如,如果/ var / www / vpath1 / html和/ var / www / html /和/ var / www / vpath2 / html中存在index.php,并且每个虚拟都映射到/ var / www / html,那么无论使用哪个虚拟服务器,都将看到/ var / www / html。
Mark Richards 2014年

1
@ChristofferBubach您甚至不需要抛出它:异常对象在构造过程中收集堆栈跟踪。
zerkms '18


241
echo realpath(dirname(__FILE__));

如果将其放置在包含文件中,它将打印此包含文件的路径。要获取父脚本的路径,请替换__FILE__$_SERVER['PHP_SELF']。但是请注意,PHP_SELF存在安全风险!


1
这正是我想要的
2011年

13
这里的realpath有什么用?
常识

11
@Col。Shrapnel:“自PHP 4.0.2起,__FILE__始终包含已解析符号链接的绝对路径,而在旧版本中,在某些情况下,它包含相对路径。” 加“目录名称()天真操作输入字符串,并且不知道实际的文件系统的,或路径组分如‘..’。
瑞克

6
哦,4.0.2。上世纪?
您的常识

2
@rik:而且,什么安全问题会导致PHP_SELF??
zerkms 2011年

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,如果在c.php中进行了检查,则包含树应该是a.php的路径。似乎可靠的唯一方法是使用debug_backtrace()函数。
inquam 2015年

5
`realpath(dirname(__FILE__))` 

它为您提供当前脚本(在其中放置了此代码的脚本)目录,且不带斜杠。如果您要在结果中包含其他文件,这很重要


是的,但是这个主意是即使A.php包含在B.php中,也能够获得“射击脚本” A.php的绝对路径。可以或当然可以通过存储初始脚本以供以后访问来完成,但是问题是如果不这样做就可以获取它。

4

如果您正在寻找相对于服务器根目录的绝对路径,我发现这很好用:

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

当我针对不同的服务器检查该解决方案时,无论主机的操作系统(Windows和Linux)如何,它总是为我提供dir分隔符之类的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'])

对于在Web服务器下运行的$_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

一种简单的方法具有的绝对路径最初执行的脚本,该脚本包含与任何其他脚本includerequirerequire_once是通过使用一个恒定,并在开始的存储有当前脚本路径主要脚本

define( 'SCRIPT_ROOT', __FILE__ );

当只有一个“主”脚本可以 include大多数Web应用程序中那样,与其他所有需要的脚本一起使用时,。

如果不是这种情况,并且可能有多个“初始脚本”,则为避免重新定义并在常量中存储正确的路径,每个脚本都可以以以下内容开头:

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()是不必要的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.