我有一个在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的问题不会出现同样的问题 src
和 href
属性,可以使用相对路径(没有 project_name
路径中的文件夹)。但是,我不明白为什么。因为如果标题 location
导致浏览器将relative-URL附加到当前位置,为什么在查找时它没有相同的行为 .css
要么 .js
文件。
所以... 这为我提出了几个问题:
- 如果我有虚拟主机,我会遇到这个问题吗?
- 解决这个问题的最佳方法是什么?
- 最好只拥有完整的绝对URL?
- 为什么要做HTML
src
和 href
属性不共享此行为?
现在我找到的唯一解决方案是:
define('BASE_URL','http://localhost/project_name');
header('location: '.BASE_URL.'/another_controller/method/');
但这并不完美,因为它导致我必须改变
每当域名或文件夹名称时,这定义了常量BASE_URL
变化。
您不需要更改定义的常量。可以动态找到这些值。
例:
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);
此外,您可以将重定向包装到可以同时处理两者的函数中,而不是担心是指定绝对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;
}
最后,正如@HarshSanghani在评论中提到的,你的基本路径 .htaccess
文件 应该 匹配代码中的基本路径。因此,如果 BASE_PATH
(基于上面的例子)输出 /project_name/
那么你的 .htaccess
应该容纳它:
RewriteBase /project_name/
回答你的问题:
- 这取决于您的虚拟主机的配置方式。
- 您可以简单地动态生成BASE_URL:
$baseUrl = dirname($_SERVER['SCRIPT_NAME']);
。这样,如果您的文件夹或域发生更改,则无需更改任何代码。
- 您不需要域部分。
- HTML
src
和 href
由您的浏览器解释,考虑到页面的 <base>
标签。页面上的所有路径都带有 <base>
标签会被您的浏览器相应更改。
您从服务器发送的HTTP标头(用于重定向)与您发送的html页面无关,因此不会更新。
您应该在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]