ThinkPHP采用单一入口模式访问应用,对应用的所有请求都定向到应用的入口文件,系统会从URL参数中解析当前请求的模块、控制器和操作,下面是一个标准的URL访问格式:

模块/控制器/操作

其中index.php就称之为应用的入口文件(注意入口文件可以被隐藏,后面会提到)

模块在ThinkPHP中的概念其实就是应用目录下面的子目录,而官方的规范是目录名小写,因此模块全部采用小写命名,无论URL是否开启大小写转换,模块名都会强制小写

应用的index模块的Index控制器定义如下:

<?php namespace app\index\controller; class Index { public function index() { return 'index'; } public function hello($name = 'World') { return 'Hello,' . $name . '!'; } }

如果直接访问入口文件的话,由于URL中没有模块、控制器和操作,因此系统会访问默认模块(index)下面的默认控制器(Index)的默认操作(index),因此下面的访问是等效的:


如果要访问控制器的hello方法,则需要使用完整的URL地址

访问URL地址后页面输出结果为:

Hello,thinkphp!

由于name参数为可选参数,因此也可以使用

访问URL地址后页面输出结果为:

Hello,World!

默认情况下,URL地址中的控制器和操作名是不区分大小写的,因此下面的访问其实是等效的:


如果控制器是驼峰的,例如定义一个HelloWorld控制器(application/index/controller/HelloWorld.php):

<?php namespace app\index\controller; class HelloWorld { public function index($name = 'World') { return 'Hello,' . $name . '!'; } }

正确的URL访问地址(该地址可以使用url方法生成)应该是

系统会自动定位到HelloWorld控制器类去操作

如果使用

将会报错,并提示Helloworld控制器类不存在

如果希望严格区分大小写访问(这样就可以支持驼峰法进行控制器访问),可以在应用配置文件中设置:

// 关闭URL自动转换(支持驼峰访问控制器) 'url_convert' => false,

关闭URL自动转换之后,必须使用下面的URL地址访问(控制器名称必须严格使用控制器类的名称,不包含控制器后缀):


如果服务器环境不支持pathinfo方式的URL访问,可以使用兼容方式,例如:

?s=/index/Index/index

其中变量s的名称的可以配置的

5.0不再支持普通的URL访问方式,所以下面的访问是无效的,你会发现无论输入什么,访问的都是默认的控制器和操作

?m=index&c=Index&a=hello

参数传入

通过操作方法的参数绑定功能,可以实现自动获取URL的参数,仍然以上面的控制器为例,控制器代码如下:

<?php namespace app\index\controller; class Index { public function index() { return 'index'; } public function hello($name = 'World') { return 'Hello,' . $name . '!'; } }

当我们访问

就是访问app\index\controller\Index控制器类的hello方法,因为没有传入任何参数,name参数就使用默认值World。如果传入name参数,则使用:

页面输出结果为:

Hello,thinkphp!

现在给hello方法增加第二个参数:

public function hello($name = 'World', $city = '') { return 'Hello,' . $name . '! You come from ' . $city . '.'; }

访问地址为

页面输出结果为:

Hello,thinkphp! You come from shanghai.

可以看到,hello方法会自动获取URL地址中的同名参数值作为方法的参数值,而且这个参数的传入顺序不受URL参数顺序的影响,例如下面的URL地址输出的结果和上面是一样的:

或者使用?city=shanghai&name=thinkphp

还可以进一步对URL地址做简化,前提就是我们必须明确参数的顺序代表的变量,我们更改下URL参数的获取方式,把应用配置文件中的url_param_type参数的值修改如下:

// 按照参数顺序获取 'url_param_type' => 1,

现在,URL的参数传值方式就变成了严格按照操作方法的变量定义顺序来传值了,也就是说我们必须使用下面的URL地址访问才能正确传入name和city参数到hello方法:

页面输出结果为:

Hello,thinkphp! You come from shanghai.

如果改变参数顺序为

页面输出结果为:

Hello,shanghai! You come from thinkphp.

显然不是我们预期的结果。

同样,我们试图通过

访问也不会得到正确的结果

[注意]按顺序绑定参数的话,操作方法的参数只能使用URL pathinfo变量,而不能使用get或者post变量

隐藏入口

可以去掉URL地址里面的入口文件index.php,但是需要额外配置WEB服务器的重写规则。

以Apache为例,需要在入口文件的同级添加.htaccess文件(官方默认自带了该文件),内容如下

<IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] </IfModule>

如果用的phpstudy,规则如下:

<IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1] </IfModule>

接下来就可以使用下面的URL地址访问了


如果使用的apache版本使用上面的方式无法正常隐藏index.php,可以尝试使用下面的方式配置.htaccess文件:

<IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L] </IfModule>

如果是Nginx环境的话,可以在Nginx.conf中添加:

location / { // …..省略部分代码 if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=/$1 last; break; } }

定义路由

URL地址里面的index模块怎么才能省略呢,默认的URL地址显得有点长,下面就来说说如何通过路由简化URL访问。

我们在路由定义文件(application/route.php)里面添加一些路由规则,如下:

return [ // 添加路由规则 路由到 index控制器的hello操作方法 'hello/:name' => 'index/index/hello', ];

该路由规则表示所有hello开头的并且带参数的访问都会路由到index控制器的hello操作方法。

路由之前的URL访问地址为:

定义路由后就只能访问下面的URL地址

[注意]定义路由规则后,原来的URL地址将会失效,变成非法请求。

但这里有一个小问题,如果我们只是访问

将发生错误

事实上这是由于路由没有正确匹配到,我们修改路由规则如下:

return [ // 路由参数name为可选 'hello/[:name]' => 'index/hello', ];

使用[]把路由规则中的变量包起来,就表示该变量为可选,接下来就可以正常访问了

当name参数没有传入值的时候,hello方法的name参数有默认值World,所以输出的内容为 Hello,World!