用PHP编写路由谜语

时间:2016-09-04 08:40:05

标签: php .htaccess url-rewriting routing

我用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请求?

2 个答案:

答案 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']