PHP 的 $_GET 和 URL 重写
Posted
技术标签:
【中文标题】PHP 的 $_GET 和 URL 重写【英文标题】:$_GET and URL Rewriting for PHP 【发布时间】:2010-10-05 01:20:32 【问题描述】:URL 重写如何影响 php 的 $_GET
参数?
假设我有一个类似 http://example.com/index.php?p=contact
的 URL,我使用 $_GET['p']
告诉 index.php
提供联系页面。如果我使用将 URL 转换为 http://example.com/contact
的重写规则,$_GET['p']
是否仍能按预期工作?
如果可以,您能否详细说明它为什么有效?如果不是,可以使用什么策略来解决问题,以便页面在重写和不重写的情况下都能正常工作?
【问题讨论】:
现在说真的,只有我一个人注意到他正在尝试将example.com/index.php?p=contact 转换为example.com/contact,而不是像这里的每个人一样将example.com/contact 转换为example.com/index.php?p=contact??跨度> 我误解了它的工作原理,但这里的答案有助于纠正我的理解。 【参考方案1】:我会将格兰特的回答修改为“是的,这将大部分按预期工作。”
具体来说,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]
(“查询字符串追加”)标志,这会将原始查询字符串放置在规则中提供的参数之后,翻译@987654330 @到/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']
在使用此规则时将始终返回“联系人”,无论您的访问者是否在弄乱您的网址。 :-)
【讨论】:
嗯,同样的事情在周末让我措手不及,所以我想我会分享。 :-) 我会从查询字符串中完全去掉“联系人”这个词:RewriteRule ^(.+)$ index.php/$1
表示“联系人”可以在$_SERVER['PATH_INFO']
中访问,而不是在$_GET['q']
中。其他$_GET
参数不受影响。【参考方案2】:
是的,这将按预期工作。
【讨论】:
那么重写是否只是覆盖浏览器中地址栏的 URL,但仍将未写入的 URL 提供给脚本? 您输入 www.example.com/page/8 并 rewrite 看到 page/8 并将其更改为 index.php?page=8 在您的 php 脚本看到它之前。 rewrite 可以在内部更改 URL 而无需告诉用户,或者立即将他/她重定向到新的 url,具体取决于您使用的参数。如果您告诉它,它甚至可以代理来自另一台服务器的新页面。 这完全取决于你的 RewriteRule 是什么【参考方案3】:重写 URL 时,这由 mod_rewrite 完成——最终检索到的页面仍然是“旧”页面,即 index.php?p=contact。换句话说,浏览器检索 /contact。 mod_rewrite 然后将其重写为 index.php?p=contact。由于这个原因,脚本不知道发生了任何重写——它仍然被称为“通常”的方式。因此,这样的重写将起作用。您可能想将其视为一种重写代理,它请求的页面与原始浏览器请求的页面不同。
【讨论】:
【参考方案4】:当客户端请求http://example.com/contact 时,服务器使用重写规则来为它们提供http://example.com/index.php?p=contact。客户端将无法看到重写的 URL,甚至可能无法判断它已被重写。以客户端的身份请求任一 URL 将为您提供完全相同的页面。
【讨论】:
【参考方案5】:难道不是在渲染部分页面后修改标题会导致php页面搞砸吗?你是如何重写 URL 的?可能是我误会了……
【讨论】:
我认为使用 mod_rewrite 或类似的东西 重写将通过 Apache 重写规则。我对此不太了解,因此提出了这个问题,但我认为标题根本没有被触及。 您是否可以使用 POST 而不是 GET,然后在您的 webdir 中创建一个子目录 ROOT/contact,其 Apache INDEX 指向正确的页面?有点奇怪的解决方案,但它可以解决上述两个问题......【参考方案6】:您将 URL 从 /contact
重写为 /index.php?p=contact
,所以是的,它会按预期工作。
【讨论】:
【参考方案7】:在你的情况下它不会工作。 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'
【讨论】:
这取决于重写规则是什么。根据规则,它可能容易受到进一步规则的影响,或者就停在那里。您可能会丢失 get vars,但这取决于重写规则,VirtuosiMedia 尚未开始构建,因此无论如何这是一个有争议的问题。 好吧,在他的情况下,从 example.com/index.php?p=contact 到 example.com/contact 会剥夺你的任何 GET 变量,所以没有 $_GET['p'] 不起作用。 @kRON:你不觉得它也会剥夺你的剧本吗? 如果它依赖于 $_GET['p'],那么它肯定会剥夺你的工作脚本。 我知道你来自哪里。不,Virtuosi 正在走另一条路。用户键入 /contact,他会看到 index.php?page=contact。他写的好像重写规则改变了用户的 URL,而不是用户的。以上是关于PHP 的 $_GET 和 URL 重写的主要内容,如果未能解决你的问题,请参考以下文章