包含重写

时间:2016-05-02 09:29:44

标签: php .htaccess mod-rewrite relative-path absolute-path

我有一个在WampServer上运行本地的项目。这是一个类似MVC的结构;它将URL重写为index.php?url=$1。完整.htaccess

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]

当我想使用PHP location: <location>将用户发送到另一个页面时,由于重写,所以它没有正确执行此操作(尽管我在技术上始终位于index.php中)。

例如,如果我在http://localhost/project_name/controller/method/并且此控制器的构造函数或方法试图将我发送到:

  • header('location: another_controller/method');送我去 http://localhost/project_name/controller/method/another_controller/method/
  • header('location: /another_controller/method');送我去 http://localhost/another_controller/method/

但我希望它像这样发送给我:

  • header('location: /another_controller/method');送我去 http://localhost/project_name/another_controller/method/

现在我找到的唯一解决方案是:

define('BASE_URL','http://localhost/project_name');
header('location: '.BASE_URL.'/another_controller/method/');

但这并不完美,因为只要域名或文件夹名称发生变化,我就必须更改此定义的常量BASE_URL。我还可以在我的BaseController中创建一个创建绝对URL的方法,但这种方法基本上也只是BASE_URL的前缀。

注意: HTML的srchref属性不会出现同样的问题,这些属性可以使用相对路径(路径中没有project_name文件夹) 。但是,我不明白为什么。因为如果标头location导致浏览器将相对URL附加到当前位置,那么在查找.css.js文件时,为什么它不具有相同的行为。< / p>

所以...... 这为我提出了几个问题:

  1. 如果我有虚拟主机,我会遇到这个问题吗?
  2. 解决此问题的最佳方法是什么?
  3. 最好是拥有完整的绝对网址吗?
  4. 为什么HTML的srchref属性不会共享此行为?

4 个答案:

答案 0 :(得分:4)

  

现在我找到的唯一解决方案是:

if ($_SERVER['DOCUMENT_ROOT'] == dirname($_SERVER['SCRIPT_FILENAME'])) {
    define('BASE_PATH', '/');
} else {
    define('BASE_PATH', dirname($_SERVER['SCRIPT_NAME']) . '/');
}

$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
define('BASE_URL', $protocol . $_SERVER['SERVER_NAME'] . BASE_PATH);
     

但这并不完美,因为它导致我必须改变   每当域或文件夹名称时,这定义了常量BASE_URL   变化。

您不需要更改已定义的常量。这些值可以动态找到。

示例:

function redirect($path = null) {
    if (isset($path)) {
        if (filter_var($path, FILTER_VALIDATE_URL)) {
            header('Location: ' . $path);
        } else {
            header('Location: ' . BASE_URL . $path);
        }
    } else {
        header('Location: ' . BASE_URL);
    }
    exit;
}

此外,您可以将重定向包装到可以同时处理这两者的函数中,而不是担心是指定绝对URL还是路径:

.htaccess

最后,正如@HarshSanghani在评论中提到的,BASE_PATH文件中的基本路径应与代码中的基本路径匹配。因此,如果/project_name/(基于上面的示例)输出.htaccess,那么您的RewriteBase /project_name/ 应该适应它:

{{1}}

答案 1 :(得分:2)

回答你的问题:

  1. 这取决于您的虚拟主机的配置方式。
  2. 您可以简单地动态生成BASE_URL:$baseUrl = dirname($_SERVER['SCRIPT_NAME']);。这样,如果您的文件夹或域名发生更改,则无需更改任何代码。
  3. 您不需要域名部分。
  4. html srchref由您的浏览器解释,其中考虑了网页的<base>标记。带有<base>标记的网页上的所有路径都会相应地由您的浏览器更改。
  5. 您从服务器发送的HTTP标头(用于重定向)与您发送的html页面无关,因此不会更新。

答案 2 :(得分:2)

  1. 如果您在子目录中设置了项目,则会出现此问题。如果你想在project_name.localhost设置它们,那么使用虚拟主机可以解决问题。
  2. 在我的项目中,我使用环境变量为开发,登台或生产加载不同的配置文件。在这里我设置了$baseUri某种方式。
  3. 使用绝对网址(包括域名)解决此问题和搜索引擎优化的最佳做法。在功能方面,您不需要域名部分。
  4. src和href标签通常以相同的方式工作,但正如Andreas所说,它们可能会受到基本标签的影响。

答案 3 :(得分:2)

您应该在htaccess文件中指定RewriteBase。在链接中使用相对路径,您不需要任何其他路径。

RewriteBase /project_name/
RewriteEngine on
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]