【问题标题】:Full URL with directory path to a file带有文件目录路径的完整 URL
【发布时间】:2012-05-29 13:09:39
【问题描述】:

我自己正在寻找一种方法来做到这一点,并想出了这个方法:

<?php
$script_name = $_SERVER['SCRIPT_NAME']; // to get www.myurl.com

// create a constant out of the server_name
define('HTTP_HOST', $_SERVER['HTTP_HOST'].'/');

$path_parts = pathinfo($script_name); // returns an array with path names

// get the filename with the extension
$file_name = $path_parts['filename'] . '.' . $path_parts['extension'];
// get the directory which the script lives in
$dir = rtrim($script_name, $file_name);
// trim of the left slash since it was added on the end of the HTTP_HOST constant
$dir = ltrim($dir, '/');
// store the server name and directory paths in a variable
$dir = HTTP_HOST.$dir;

echo $dir; // will return f.ex. "www.myurl.com/dir1/dir2/dir3/"

假设我有一个名为“testfile.php”的文件,它位于“www.myurl.com/dir1/dir2/dir3”的目录“dir3”下,所以完整的 url 将是“www.myurl.com/dir1/dir2/dir3/testfile.php”。

如果我在我的路径文件中为 URL 加上完整目录路径声明一个常量,或者我在我的索引文件 f.ex 中包含的一些配置文件,并在 testfile.php 中调用该常量 end echo 它。它会回显“www.myurl.com/dir1/dir2/dir3/”。

我的问题是,这种方法是否可以接受,还是有更好的方法来实现带有给定文件的目录路径的 URL?

谢谢。

【问题讨论】:

    标签: php apache model-view-controller path


    【解决方案1】:

    众所周知,完美主义是很难实现的。这意味着通常有更好的方法来实现目标。

    查看您问题中的代码,我很确定,有更好的方法来实现您正在寻找的内容。回到你的问题:

    我的问题是,这种方法是否可以接受,还是有更好的方法来实现带有给定文件的目录路径的 URL?

    答案是肯定的。例如,更好的方法是将实现封装到它自己的对象中,例如一个文件映射器。这将允许您始终使用随时间变化的最佳方式。

    您至少应该从一个函数开始,该函数封装了将文件名映射到 web 目录的逻辑。还要利用所谓的输入,并在代码顶部处理它们:

    function get_webdirectory_of_file($file)
    {
       # input (and validation)
    
       $host = $_SERVER['HTTP_HOST'];
       $docroot = $_SERVER['DOCUMENT_ROOT'];
    
       if (!is_file($file) {
           throw new Exception('Not a file');
       }
    
       if (!$host) {
           throw new Exception('No HTTP_HOST found.');
       }
    
       if (!$docroot ) {
           throw new Exception('No DOCUMENT_ROOT found.');
       }  
    
       $len = strlen($docroot);
    
       if (substr($file, 0, $len) !== $docroot) {
           throw new Exception('Unable to map file out of document root to document root');
       }
    
       # processing
    
       $dir = substr(dirname($file), $len);
    
       # output 
    
       return $host . $dir;
    }
    

    由于代码位于它自己的函数中,因此您可以随着时间的推移对其进行改进,而无需更改(大部分)应用程序的其余部分。使用对象会更好,因为您可以更轻松地替换它,从而使整体更加灵活,但从函数开始也是一个好主意。使用示例:

     echo get_webdirectory_of_file(__FILE__);
    

    查看您的代码:

    <?php
    $script_name = $_SERVER['SCRIPT_NAME']; // to get www.myurl.com
    

    有关使用 $_SERVER 变量的问题,请查看 PHP 手册。

    // create a constant out of the server_name
    define('HTTP_HOST', $_SERVER['HTTP_HOST'].'/');
    

    由于$_SERVER['HTTP_HOST'] 已经存在,因此无需创建常量。这只会隐藏以后使用该常量的相关问题。我建议您从代码中删除该常量。

    $path_parts = pathinfo($script_name); // returns an array with path names
    
    // get the filename with the extension
    $file_name = $path_parts['filename'] . '.' . $path_parts['extension'];
    

    实际上,您在这里寻找的是basename,就是这样:

    $file_name = basename($_SERVER['SCRIPT_NAME']);
    

    现在开始使用您的代码:

    // get the directory which the script lives in
    $dir = rtrim($script_name, $file_name);
    

    这有点痛。请重新阅读rtrim 函数的作用。你不想在这里使用它。

    // trim of the left slash since it was added on the end of the HTTP_HOST constant
    $dir = ltrim($dir, '/');
    

    在这种情况下使用ltrim 可能看起来很聪明,但通常这是一种你不了解你实际做什么以及你使用哪些输入值工作的气味。与使用常量进行比较:

    // store the server name and directory paths in a variable
    $dir = HTTP_HOST.$dir;
    

    您在此处重复使用变量名 ($dir)。这通常没有帮助。此外,如果您首先添加/ 只是为了删除/ 上面的一行,这没有任何意义。两者都可以。

    echo $dir; // will return f.ex. "www.myurl.com/dir1/dir2/dir3/"
    

    当然,问题是你需要什么以及它有多稳定。正如所写,我完全确定,有更好的方法来做到这一点,是的。

    【讨论】:

    • 我知道我还有一些阅读要做:),感谢您提供这些宝贵的信息。
    • @VilliMagg:我也给你添加了一个代码示例,希望它很容易理解。
    • 谢谢,我会试试你的代码,让你知道它是如何工作的:)
    【解决方案2】:

    这应该可行:

    $dir = $_SERVER['HTTP_HOST'] . substr(dirname(__FILE__), strlen($_SERVER['DOCUMENT_ROOT']));
    

    【讨论】:

    • 完美运行! :) 谢谢。
    • __FILE__ 返回真实路径,如果网络服务器使用别名指令或文件系统具有符号链接,则 substr 将不起作用。这是脆弱的。
    • @hakre,你是对的。为了摆脱符号链接问题,我们必须使用$_SERVER["SCRIPT_FILENAME"] 而不是__FILE__。对于别名 - 由于文件不在根目录中,因此没有解决方案。需要处理这种情况。但是同样,如果我们使用 cgi 运行 php - 那么 $_SERVER 数组可能无法完全设置,并且它再次脆弱:) 需要考虑大多数,对于大多数它会解决问题。
    • 由于您无法涵盖所有​​情况,请封装变化的内容,例如将其放入具有已定义接口的自己的对象中。
    • 好的,所以我使用substr(dirname($_SERVER["SCRIPT_FILENAME"]), strlen($_SERVER["DOCUMENT_ROOT"])) 而不是dirname(__FILE__)?
    【解决方案3】:

    看看这是否有效:

    function getCurrentPageURL() {
      $protocol = "http";
      if ($_SERVER["HTTPS"] == "on") {$protocol .= "s";}
      $protocol .= "://";
    
      $server = $_SERVER["SERVER_NAME"];
    
      if ($_SERVER["SERVER_PORT"] != "80") {
          $page = $server .  ":" . $_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
       } else {
          $page = $server . $_SERVER["REQUEST_URI"];
       }
       return $protocol . $pageURL;
    }
    

    此解决方案考虑了不同的端口和 HTTPS 协议。

    【讨论】:

    • 这个函数有一些好东西。虽然它返回了 URL + filename.php。但这很容易解决 :) 谢谢。
    • 这也返回请求参数:) 要摆脱参数需要使用SCRIPT_NAME 而不是REQUEST_URI
    猜你喜欢
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多