我用htaccess和PHP制作了简单的路由器。但这种方式使得无法在url中设置额外的GET参数。
的.htaccess
RewriteEngine On
[...]
RewriteCond %{REQUEST_URI} !\.(gif|jpg|png)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?url=$1 [PT,L]
[...]
的index.php
[...]
$url = isset($_GET['url']) ? $_GET['url'] : null;
$router = new Router($url);
[...]
然后我正在运行调度员。例如,url www.site.com/user/regierter运行class UserController -> registerAction()
。但如果我想添加另一个获取请求,例如:
的 www.site.com/user/regierter?layout=red
如何调度url部分但接受另一个get请求?
答案 0 :(得分:4)
您的重写方法不利于此用例。
简单地使用内部重定向从Web服务器获取请求到PHP并让PHP处理请求参数更容易。
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [PT]
这使得Apache httpd将任何请求(不是文档根目录中存在的文件或目录)重定向到内部的index.php
。意思是,重定向对最终用户完全透明。当您的网络服务器看到www.example.com/foo
而PHP看到/index.php
时,他们会看到/foo
。这使得无论查询字符串参数如何,都可以在内部处理路由。
$url = $_SERVER['REQUEST_URI'];
$router = new Router($url);
查询字符串中的任何参数仍然适当地在$_GET
中进行解析。 $_SERVER['REQUEST_URI']
包含您的网络服务器传递给PHP的原始请求URI,以便www.example.com/foo/bar/?quix=1&quack=2
以/foo/bar/?quix=1&quack=2
和$_GET['quix'] == 1
以及$_GET['quack'] == 2
读取$_SERVER['REQUEST_URI']
。
因此,就PHP而言,原始查询字符串(即HTTP请求行)保持不变。这里唯一的变化是您的Web服务器如何确定是否让PHP处理请求或直接从文档根目录提供请求。
现在,您的路由器可以直接从var_dump(parse_url($_SERVER['REQUEST_URI']))
中提取所需的所有信息,例如parse_url
。
因此,如果向 www.site.com/user/register?layout=red $_GET['layout']
发出请求,则会给您这样的信息。
array(2) { ["path"]=> string(14) "/user/register" ["query"]=> string(10) "layout=red" }
"red"
仍然会给你String UcharSet = "[a-zA-Z0-9-~!_#(@).]+";
boolean UMORN = UserName.matches(UcharSet);
if(!UMORN)
PopMyError();
。
答案 1 :(得分:2)
如果您的目标(index.php)是别名或类似的
,则只需要RewriteRule
标志PT|passthrough
也就是说,使用[PT]标志会导致RewriteRule的结果通过URL映射传回,因此基于位置的映射(例如Alias,Redirect或ScriptAlias)可能会有机会生效。
所以在你的情况下这没有帮助,使用标志L|last
就足够了。
正如@arkascha已经提到的,为了保持其他获取参数,你必须使用QSA|qsappend
标志
当替换URI包含查询字符串时,RewriteRule的默认行为是丢弃现有的查询字符串,并将其替换为新生成的查询字符串。使用[QSA]标志会导致查询字符串合并。
这意味着您的规则将成为
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?url=$1 [L,QSA]
这将在PHP脚本中为您提供$_GET['url']
和 $_GET['layout']
。