【问题标题】:Get absolute path of initially run script获取初始运行脚本的绝对路径
【发布时间】:2011-06-06 09:58:46
【问题描述】:

我搜索了高低,并获得了许多不同的解决方案和包含信息的变量以获得绝对路径。但它们似乎在某些条件下有效,而在其他条件下无效。有没有一种灵丹妙药的方法来获取 PHP 中执行脚本的绝对路径?对我来说,脚本将从命令行运行,但是,如果在 Apache 等中运行,解决方案应该也能正常运行。

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

【问题讨论】:

  • 确实是 mathheadinclouds。我很久以前就接受了它,当时我只有一个脚本并且它对我有用。我删除了接受的答案,以明确它不能解决最初的问题。在脚本中开始执行时存储 FILE 常量是一种方法,但远非理想。
  • 请求的脚本是你想要的,当前脚本=这个解决方案代码

标签: php path include


【解决方案1】:

获取初始执行脚本的绝对路径的简单方法,在该脚本包含在includerequire、@987654325 中的任何其他脚本@ 是通过使用 constant 并将当前脚本路径存储在 主脚本 的开头:

define( 'SCRIPT_ROOT', __FILE__ );

当有一个“主”脚本 includes 每个其他需要的脚本时,上述解决方案适用,就像在大多数 Web 应用程序中一样。

如果不是这样,并且可能有多个“初始脚本”,那么为了避免重新定义并将正确的路径存储在每个脚本可能开头的常量中:

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

关于(当前)accepted answer 的说明:

答案表明最初执行的脚本路径是get_included_files()返回的数组的第一个元素。

这是一个聪明而简单的解决方案,并且 - 在撰写本文时 -(我们几乎是 PHP 7.4.0)它确实有效

但是通过查看documentation 并没有提到最初执行的脚本是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() 是不必要的。

【讨论】:

    【解决方案2】:

    如果您想获取当前工作目录,请使用getcwd()

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

    __FILE__ 将返回带有文件名的路径,例如在 XAMPP 上 C:\xampp\htdocs\index.php 而不是 C:\xampp\htdocs\

    【讨论】:

      【解决方案3】:
      __DIR__
      

      来自the manual

      文件的目录。如果在包含中使用,则返回包含文件的目录。这相当于dirname(__FILE__)。此目录名称没有尾部斜杠,除非它是根目录。
      __FILE__ 始终包含解析符号链接的绝对路径,而在旧版本(4.0.2 之前)中,它在某些情况下包含相对路径。

      注意__DIR__ 是在 PHP 5.3.0 中添加的。

      【讨论】:

        【解决方案4】:

        这是我使用的,它适用于 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']);
        }
        

        【讨论】:

          【解决方案5】:

          正确的解决方法是使用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
          

          【讨论】:

          • 这个解决方案有效,但值得一提的是,阅读documentation,没有提到初始运行脚本的路径是@返回的数组的第一个项987654328@。我 suggest__FILE__ 存储到脚本开头的常量中,这意味着最初要运行。
          【解决方案6】:

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

          更新

          问题已更改为询问如何检索最初执行的脚本而不是当前正在运行的脚本。唯一 (??) 可靠 的方法是使用 debug_backtrace 函数。

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

          【讨论】:

          • 如果我使用的是前端控制器模式。 __FILE__ 会返回 index.php 的位置还是包含文件的位置?如何获取 index.php 的位置?
          • __FILE__ 确实指向当前脚本的路径。但是我没有找到任何可以显示当前 index.php 路径的东西。
          • @CMCDragonkai:然后问一个单独的问题
          • 注意:如果脚本位于 apache2 虚拟目录中,则返回的信息不会提供物理服务器上的真实路径位置。我想要这个用于调试目的,甚至 $_SERVER 变量也不提供这个。例如,如果 index.php 存在于 /var/www/vpath1/html 和 /var/www/html/ 和 /var/www/vpath2/html 中,并且每个都虚拟映射到 /var/www/html,那么 /var/www/html 就是你所看到的,无论使用哪个虚拟服务器。
          • @ChristofferBubach 你甚至不需要抛出它:一个异常对象在构造过程中收集堆栈跟踪。
          【解决方案7】:
          realpath($_SERVER['SCRIPT_FILENAME'])
          

          对于在网络服务器$_SERVER['SCRIPT_FILENAME'] 下运行的脚本,将包含最初调用脚本的完整路径,因此可能是您的 index.php。在这种情况下不需要realpath()

          对于从控制台运行的脚本$_SERVER['SCRIPT_FILENAME'] 将包含从当前工作目录到您最初调用的脚本的相对路径。因此,除非您更改脚本中的工作目录,否则它将解析为绝对路径。

          【讨论】:

            【解决方案8】:

            这是我为此专门编写的一个有用的 PHP 函数。正如原始问题所阐明的那样,它返回执行 initial 脚本的路径,而不是我们当前所在的文件。

            /**
             * 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;
            }
            

            【讨论】:

              【解决方案9】:

              在你的脚本上试试这个

              echo getcwd() . "\n";
              

              【讨论】:

                【解决方案10】:

                只需在下面使用:

                echo __DIR__;
                

                【讨论】:

                • 抱歉,我们的想法是获取第一个触发的脚本......不是你现在碰巧遇到的那个。因此,如果在 c.php 中选中,a.php->b.php->c.php 的包含树应该是 a.php 的路径。似乎可靠的唯一方法是使用 debug_backtrace() 函数。
                【解决方案11】:
                `realpath(dirname(__FILE__))` 
                

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

                【讨论】:

                • 是的,但我们的想法是即使在 B.php 中也能够获得“触发脚本”A.php 的绝对路径(如果 A.php 包含该路径)。它可以或当然通过存储初始脚本以供以后访问来完成,但问题是是否有可能在不这样做的情况下获得它。
                【解决方案12】:
                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/

                【讨论】:

                  【解决方案13】:

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

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

                  【讨论】:

                  • 当我针对不同的服务器检查此解决方案时,无论主机的操作系统(Windows 和 Linux)如何,它总是为我提供了 linux 的路径,例如 dir 分隔符。对我来说这是一个优势。
                  【解决方案14】:
                  echo realpath(dirname(__FILE__));
                  

                  如果你把它放在一个包含的文件中,它会打印到这个包含的路径。要获取父脚本的路径,请将__FILE__ 替换为$_SERVER['PHP_SELF']。但请注意 PHP_SELF 存在安全风险!

                  【讨论】:

                  • 这正是我想要的
                  • 这里的realpath有什么用?
                  • 使用$_SERVER['PHP_SELF']有什么安全风险?因为人们回显它并且它包含可能是恶意的 URL?
                  • @Col。弹片:“从 PHP 4.0.2 开始,__FILE__ 总是包含一个绝对路径,符号链接已解析,而在旧版本中,它在某些情况下包含相对路径。”加上 "dirname() 天真地对输入字符串进行操作,并且不知道实际的文件系统或路径组件,例如 '..'。
                  • @rik:另外,什么安全问题会导致PHP_SELF ??
                  猜你喜欢
                  • 2013-06-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-08-26
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-04-14
                  • 2016-08-12
                  相关资源
                  最近更新 更多