PHP 的 $_GET 和 URL 重写
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/505338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
$_GET and URL Rewriting for PHP
提问by VirtuosiMedia
How does URL rewriting affect the $_GETparameter for PHP?
URL 重写如何影响$_GETPHP的参数?
Say I have a URL like http://example.com/index.php?p=contactand I use $_GET['p']to tell index.phpto serve the contact page. If I use a rewrite rule that converts the URL to http://example.com/contact, will $_GET['p']still work as expected?
假设我有一个类似的 URL http://example.com/index.php?p=contact,我$_GET['p']用来告诉index.php联系页面。如果我使用一个重写规则,转换网址http://example.com/contact,将$_GET['p']仍然按预期工作?
If it does, could you elaborate on why it works? If not, what strategies could be used to solve the problem so that the page will work both with and without the rewrite?
如果是这样,你能详细说明它为什么起作用吗?如果不是,可以使用什么策略来解决问题,以便页面在重写和不重写的情况下都能正常工作?
采纳答案by Grant
Yes, that will work as expected.
是的,这将按预期工作。
回答by Ben Blank
I'd amend Grant's answer to "Yes, that will work mostlyas expected."
我会将格兰特的回答修改为“是的,这将主要按预期工作。”
Specifically, mod_rewrite's behavior with regards to existing query strings can be surprising. As an example, let's take the following rule, which converts the URL you supplied:
具体来说,mod_rewrite对现有查询字符串的行为可能令人惊讶。例如,让我们采用以下规则来转换您提供的 URL:
RewriteRule /contact /index.php?p=contact
This will correctly rewrite /contactto /index.php?p=contactand the page name will be accessible through $_GET['p']. However, if you use this technique with a script that uses parameters other than the page name, it gets slightly trickier. This rule also translates /contact?person=Joeto /index.php?p=contact. The person=Joeparameter disappears entirely! There are two ways to deal with this.
这将正确地重写/contact为,/index.php?p=contact并且可以通过$_GET['p']. 但是,如果您将此技术与使用页面名称以外的参数的脚本一起使用,它会变得有点棘手。此规则也转化/contact?person=Joe为/index.php?p=contact. 该person=Joe参数完全消失!有两种方法可以解决这个问题。
The simplest way is to use the [QSA]("query string append") flag on your rule, which will place the original query string afterthe parameters supplied in the rule, translating /contact?person=Joeto /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]
However, this makes it possible for your p=parameter to get overwritten. Visiting /contact?p=aboutwill get rewritten to /index.php?p=contact&p=about, so $_GET['p']will return "about" in your script, not "contact". To resolve this, use the QUERY_STRINGvariable instead:
但是,这可能p=会覆盖您的参数。Visiting/contact?p=about将被重写为/index.php?p=contact&p=about,因此$_GET['p']将在您的脚本中返回“about”,而不是“contact”。要解决此问题,请改用QUERY_STRING变量:
RewriteRule /contact /index.php?%{QUERY_STRING}&p=contact
This guarantees that $_GET['p']will alwaysreturn "contact" when using this rule, regardless of whether your visitors are messing with your URLs. :-)
这保证了$_GET['p']将永远使用这个法则时,无论您的访问者与您的网址搞乱的回归“接触”。:-)
回答by bluebrother
When rewriting an URL this is done by mod_rewrite -- the page retrieved in the end is still the "old" one, i.e. index.php?p=contact. In other words, the browser retrieves /contact. mod_rewrite then rewrites it to index.php?p=contact. The script, due to this, doesn't know that any rewriting happened -- it still gets called its "usual" way. Therefore such a rewrite will work. You might want to think of it as a rewriting proxy that requests a different page than the one the originating browser requested.
当重写 URL 时,这是由 mod_rewrite 完成的——最终检索到的页面仍然是“旧”页面,即 index.php?p=contact。换句话说,浏览器检索 /contact。mod_rewrite 然后将其重写为 index.php?p=contact。因此,脚本不知道发生了任何重写——它仍然被称为“通常”的方式。因此,这样的重写将起作用。您可能希望将其视为一种重写代理,它请求与原始浏览器请求的页面不同的页面。
回答by Jeremy Ruten
When the client requests http://example.com/contact, the server uses the rewrite rule to serve them http://example.com/index.php?p=contactinstead. The client will not be able to see the rewritten URL and might not even be able to tell that it was rewritten. Requesting either URL as the client would give you the exact same page.
当客户端请求http://example.com/contact 时,服务器使用重写规则为它们提供服务http://example.com/index.php?p=contact。客户端将无法看到重写的 URL,甚至可能无法判断它已被重写。作为客户端请求任一 URL 都会为您提供完全相同的页面。
回答by SilentGhost
You rewrite URL from /contactto /index.php?p=contact, so yes, it'll work as expected.
您将 URL 从/contactto重写/index.php?p=contact,所以是的,它会按预期工作。
回答by Brian Sweeney
Isn't it the case that modifying the headers after having rendered parts of the page can cause screw ups in php pages? How are you rewriting the URL? Maybe I misunderstand...
在呈现页面的某些部分后修改标题不是会导致php页面搞砸吗?你是如何重写URL的?可能我理解错了...
回答by Filip Dupanovi?
In your case it wouldn't work. mod_rewrite, after it finds a match and rewrites http://example.com/index.php?p=contactto http://example.com/contact, does an internal redirect. Even after the redirect, the new, redirected URI, can still be matched against a condition and further redirected.
在你的情况下它不会工作。mod_rewrite 在找到匹配项并将http://example.com/index.php?p=contact重写为 http://example.com/contact 后,会进行内部重定向。即使在重定向之后,新的、重定向的 URI 仍然可以与条件匹配并进一步重定向。
In any case, incoming URIs aren't kept in memory, so not even Apache can reconstruct what the original URI was. PHP, by the time it's executed, also doesn't know the original URI. Hence, you loose your $_GET vars, as variables sent via GETare contained in the URL, which was, by now, transformed, and PHP populates the associative $_GET array by parsing incoming requests.
在任何情况下,传入的 URI 都不会保存在内存中,因此即使是 Apache 也无法重建原始 URI 是什么。PHP 在执行时也不知道原始 URI。因此,您会丢失 $_GET 变量,因为通过GET发送的变量包含在 URL 中,现在该 URL 已被转换,并且 PHP 通过解析传入的请求来填充关联的 $_GET 数组。
Offering support for both would be painstaking. If you have http://domain.com/segment1/segment2/segment3you have to associate the segments with something meaningful. You'd strip your domain and explode on '/', and in your case you could say that the first segment requests the page, and from http://example.com/contact/you can extract page = 'contact'
为两者提供支持将是艰苦的。如果您有http://domain.com/segment1/segment2/segment3,则必须将这些段与有意义的内容相关联。您将剥离您的域并在“/”上爆炸,在您的情况下,您可以说第一段请求该页面,并且从http://example.com/contact/您可以提取 page = 'contact'

