11

URL 重写如何影响$_GETPHP 的参数?

假设我有一个类似的 URL http://example.com/index.php?p=contact,我用它$_GET['p']来告诉index.php提供联系页面。如果我使用将 URL 转换为 的重写规则http://example.com/contact,是否$_GET['p']仍能按预期工作?

如果是这样,你能详细说明它为什么有效吗?如果不是,可以使用什么策略来解决问题,以便页面在重写和不重写的情况下都可以工作?

4

7 回答 7

34

我会将格兰特的回答修改为“是的,这将大部分按预期工作”。

具体来说,mod_rewrite关于现有查询字符串的行为可能令人惊讶。例如,让我们采用以下规则,它会转换您提供的 URL:

RewriteRule /contact /index.php?p=contact

这将正确地重写/contact/index.php?p=contact并且页面名称将可以通过$_GET['p']. 但是,如果您将此技术与使用页面名称以外的参数的脚本一起使用,它会变得有点棘手。这条规则也转化/contact?person=Joe/index.php?p=contact. 参数person=Joe完全消失!有两种方法可以解决这个问题。

最简单的方法是在规则中使用[QSA]("query string append") 标志,它将原始查询字符串放在规则中提供的参数之后,转换/contact?person=Joe/index.php?p=contact&person=Joe

RewriteRule /contact /index.php?p=contact [QSA]

但是,这使得您的p=参数有可能被覆盖。访问/contact?p=about将被重写为/index.php?p=contact&p=about,因此$_GET['p']将在您的脚本中返回“about”,而不是“contact”。要解决此问题,请改用该QUERY_STRING变量:

RewriteRule /contact /index.php?%{QUERY_STRING}&p=contact

这保证了在使用此规则时$_GET['p']始终返回“联系人”,无论您的访问者是否在弄乱您的 URL。:-)

于 2009-02-02T23:39:43.943 回答
4

是的,这将按预期工作。

于 2009-02-02T23:00:13.150 回答
1

当重写 URL 时,这由 mod_rewrite 完成——最终检索到的页面仍然是“旧”页面,即 index.php?p=contact。换句话说,浏览器检索 /contact。mod_rewrite 然后将其重写为 index.php?p=contact。由于这个原因,脚本不知道发生了任何重写——它仍然被称为“通常”的方式。因此,这样的重写将起作用。您可能希望将其视为一种重写代理,它请求的页面与原始浏览器请求的页面不同。

于 2009-02-02T23:08:24.583 回答
1

当客户端请求http://example.com/contact时,服务器使用重写规则为它们提供http://example.com/index.php?p=contact。客户端将无法看到重写后的 URL,甚至可能无法判断它已被重写。以客户端的身份请求任一 URL 都会为您提供完全相同的页面。

于 2009-02-02T23:08:54.677 回答
0

您将 URL 重写为/contactto /index.php?p=contact,所以是的,它会按预期工作。

于 2009-02-02T23:02:02.333 回答
0

不是在渲染页面的一部分后修改标题会导致php页面搞砸吗?你是如何重写 URL 的?可能我理解错了...

于 2009-02-02T23:04:14.093 回答
-2

在你的情况下,它不会工作。mod_rewrite 在找到匹配项并将 http://example.com/index.php?p=contact 重写http://example.com/contact ,会进行内部重定向。即使在重定向之后,新的重定向 URI 仍然可以与条件匹配并进一步重定向。

在任何情况下,传入的 URI 都不会保存在内存中,因此即使是 Apache 也无法重建原始 URI。PHP 在执行时也不知道原始 URI。因此,您丢失了 $_GET 变量,因为通过GET发送的变量包含在 URL 中,现在已经转换,并且 PHP 通过解析传入的请求来填充关联的 $_GET 数组。

为两者提供支持将是艰苦的。如果您有http://domain.com/segment1/segment2/segment3,则必须将这些细分与有意义的东西相关联。您将剥离您的域并在“/”上爆炸,在您的情况下,您可以说第一段请求该页面,并且从http://example.com/contact/您可以提取 page = 'contact'

于 2009-02-02T23:22:21.730 回答