我没有获得所需的 URLRewrite

I'm not obtaining the desired URLRewrite

我遇到了一个奇怪的 URL 问题。我正在使用 .htaccessheader(location) 来设置网址。

我认为我正在使用 header(位置)“重置”底部的网址,但我指定的地址看起来像是附加到当前地址而不是全部替换。

我的代码是:

$route = ltrim(strtok($_SERVER['REQUEST_URI'], '?'), '/');
if($route == strtolower($route)) {

    if($route === 'contact/edit') {
            include __DIR__ . '/../myscripts/MainScript.php';
            $driver = new MainDriver();
            $page = $driver->edit();
    }elseif($route === 'contact/add' ) {
            include __DIR__ . '/../myscripts/MainScript.php';
            $driver = new MainDriver();
            $page = $driver->add();
    }else {
            include __DIR__ . '/../myscripts/MainScript.php';
            $driver = new MainDriver();
            $page = $driver->home();
    }
}else {
    http_response_code(301);
    header('location: index.php?route=' . strtolower($route));
}

.htaccess 看起来像这样:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [NC,L,QSA]
RewriteRule ^/contact/edit(new|existing)$ /index.php?route=/contact/edit [NC,L,QSA]

本地主机打开就好了。但是,如果我尝试去 localhost/contact/editNew,而不是把我带到 localhost/contact/editnew,我会被带到 localhost/contact/index.php?contact/editnew 并且欢迎页面 index.php 被加载!

我认为最后的重写规则是必须修改的内容,但我不确定。这就是为什么我在这里寻求帮助。我根据我阅读的 apache.org 上的 mod_rewrite 页面编写了该规则。

如果您需要更多详细信息来理解此问题,请告诉我。

(编辑#2)

我已将 header 调用编辑为

header('location: ' . strtolower($route);

还是得到了同样的结果,证实了问题出在我现在学习的URLRewrite规则上。你们知道如何解决这个问题吗?

您发布的代码存在一些问题...

http_response_code(301);
header('location: index.php?route=' . strtolower($route));

您在 Location header 中传递了一个 亲属 URL。 浏览器 将相对于当前 URL 解决此问题。如果请求的 URL 是 /contact/editNew 那么以上将导致重定向到 /contact/index.php?route=<route>.

你在Location中设置的URL至少应该是root-relative(以斜杠开头),或者绝对的(最好)。

这也是 301(永久)重定向,因此将由浏览器永久缓存。 (使用 302(临时)重定向测试 以避免潜在的缓存问题。)

您正在重定向到一个查询字符串 route=<route>,您也在尝试在您的 RewriteRule 指令之一中执行此操作。但是,您的 PHP 脚本仅配置为解析 URL-path - 查询字符串从请求中剥离以计算路由:

$route = ltrim(strtok($_SERVER['REQUEST_URI'], '?'), '/');

这会检索 URL 之前 查询字符串和 丢弃 查询字符串的部分。它还从 URL-path 的开头修剪 /,使其成为 relative。因此,如果您稍后使用 header('location: ' . strtolower($route)); - 您将遇到与上述相同的问题。

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [NC,L,QSA]
RewriteRule ^/contact/edit(new|existing)$ /index.php?route=/contact/edit [NC,L,QSA]

第二条规则似乎没有任何作用?在 RewriteRule 模式 上使用斜杠前缀并且在重写为 /index.php 之后出现它无论如何都不会做任何事情。

但它也不需要做任何事情,至少根据您的 PHP 脚本不需要。您的 PHP 脚本查看 请求的 URL 上的 URL-path。它没有查看重写的 URL 或查询字符串。

次要点,但第一个 RewriteRule 上的 NCQSA 标志是多余的,正则表达式可以简化为一个点。 substitution 字符串上的斜杠前缀不是必需的。例如:

RewriteRule . index.php [L]

如果您只是想将所有 URL 转换为小写,那么您可以在 .htaccess之前 您现有的指令中执行此操作:

# Convert URL to lowercase.
RewriteCond expr "tolower(%{REQUEST_URI}) =~ /(.*)/"
RewriteRule [A-Z] %1 [R=301,L]

更新: 也许您想将请求的 URL-path 作为查询字符串传递给您的脚本?但是,如前所述,您的 PHP 当前使用的是 URL-path,而不是查询字符串。

例如,您的 .htaccess 会像下面这样:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?route= [QSA,L]

您的 PHP 脚本现在将接收 route 作为查询字符串的一部分。您可以在 PHP 脚本中使用 $_SERVER['QUERY_STRING']$_GET['route'] 超全局变量来检查。 Or/and,您仍然可以检查您当前正在执行的请求 URL-path,以提供两种访问您的页面的方法。

请注意,通过上述重写,route URL-parameter 将不会出现在对主页的请求中,因为这是由 DirectoryIndex 处理的(mod_dir).