URL 重写如何影响$_GET
PHP 的参数?
假设我有一个类似的 URL http://example.com/index.php?p=contact
,我用它$_GET['p']
来告诉index.php
提供联系页面。如果我使用将 URL 转换为 的重写规则http://example.com/contact
,是否$_GET['p']
仍能按预期工作?
如果是这样,你能详细说明它为什么有效吗?如果不是,可以使用什么策略来解决问题,以便页面在重写和不重写的情况下都可以工作?
URL 重写如何影响$_GET
PHP 的参数?
假设我有一个类似的 URL http://example.com/index.php?p=contact
,我用它$_GET['p']
来告诉index.php
提供联系页面。如果我使用将 URL 转换为 的重写规则http://example.com/contact
,是否$_GET['p']
仍能按预期工作?
如果是这样,你能详细说明它为什么有效吗?如果不是,可以使用什么策略来解决问题,以便页面在重写和不重写的情况下都可以工作?
我会将格兰特的回答修改为“是的,这将大部分按预期工作”。
具体来说,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。:-)
是的,这将按预期工作。
当重写 URL 时,这由 mod_rewrite 完成——最终检索到的页面仍然是“旧”页面,即 index.php?p=contact。换句话说,浏览器检索 /contact。mod_rewrite 然后将其重写为 index.php?p=contact。由于这个原因,脚本不知道发生了任何重写——它仍然被称为“通常”的方式。因此,这样的重写将起作用。您可能希望将其视为一种重写代理,它请求的页面与原始浏览器请求的页面不同。
当客户端请求http://example.com/contact时,服务器使用重写规则为它们提供http://example.com/index.php?p=contact。客户端将无法看到重写后的 URL,甚至可能无法判断它已被重写。以客户端的身份请求任一 URL 都会为您提供完全相同的页面。
您将 URL 重写为/contact
to /index.php?p=contact
,所以是的,它会按预期工作。
不是在渲染页面的一部分后修改标题会导致php页面搞砸吗?你是如何重写 URL 的?可能我理解错了...
在你的情况下,它不会工作。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'