浅谈pathinfo

在学习thinkPHP的过程中使用控制器进行跳转,结果会定向到404页面。URL是正确的,形如http://localhost/index.php/index/index/flower/a/2/b/3。起先我认为是我代码的问题,结果我发现别人的代码可以运行。我意识到有可能是我的服务器的问题或者和Url Router有关。这件事突然就变得有意思了起来,我决定系统的去思考一下问题在哪并解决它。

先看看设计模式

thinkPHP是很出名的MVC框架,Model - View - Controller的设计模式使得我所有的交互都首先得通过Controller,再由Controller去进行其它的交互。我检查了我那简单至极的Controller没有发现错误。和Controller相关联的.php文件也没有问题。然后我发现我们老师布置的作业框架并不是完全的MVC设计模式…这个暂且不谈。那么既然代码没有问题,就是环境配置的问题了。

thinkPHP是如何通过Url Router跳转的

thinkPHP进行常规url解析之前,先检测路由,如果发现有路由规则匹配当前的pathinfo,那么URL解析则交给路由处理。

路由规则是由多条 rule=>router 规则组成的数组。

路由处理过程大概如下:

1.遍历路由规则,与当前pathinfo字符串进行匹配,如果合法,则从pathinfo中取出所需要的字符串。

2.路由中每条规则对应一个routerrouter中指定对应的模块以及方法,模块和方法可以用第1步中匹配到的字符串进行动态替代。

3.将剩余的参数都解析并写入到$_GET中。

pathinfo模式:

1
http://域名/项目名/入口文件/模块名/方法名/键1/1/键2/2

这也就是说,我如果想用thinkPHP进行URL跳转,那么我需要开启有关pathinfo的配置。结果经过查询,apache是默认开启pathinfo的,所以老师才得以直接使用而不需要相关配置。我陷入了误区,我以为我使用的是apache。结果实质上我将项目导入PHPstorm后,浏览项目时使用的是PHP直接提供的默认端口号为63342的内置服务器。真的是粗心犯错。。我把web 服务器换为apache后就可以运行了。

后记

解决了问题后,为了更加深入的了解URL解析流程,去看了ThinkPHP/Lib/Core/Dispatcher.class.php核心类。在这里贴一段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 分析PATHINFO信息
if (!isset($_SERVER['PATH_INFO'])) {
$types = explode(',', C('URL_PATHINFO_FETCH'));
foreach ($types as $type) {
if (0 === strpos($type, ':')) {
// 支持函数判断
$_SERVER['PATH_INFO'] = call_user_func(substr($type, 1));
break;
} elseif (!empty($_SERVER[$type])) {
$_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ?
substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
break;
}
}
}

看完后两个感受:

  1. 中午注释真舒服
  2. PHP果然没有好好学,很多语法都要现查

参考:

ThinkPHP中URL解析原理,以及URL路由使用教程