ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
本讲主要是了解ThinkPHP5.0的控制器的基本概念和使用方法,主要包括: [TOC] #### 什么是控制器 控制器就是MVC设计模式中的C(Controller),通常用于读取视图V(View)、完成用户输入以及处理模型数据M(Model)。 按照ThinkPHP的架构设计,所有的URL请求(无论是否采用了路由),最终都会定位到控制器(也许实际的类不一定是控制器类,但也属于广义范畴的控制器)。控制器的层可能有很多,为了便于区分就把通过URL访问的控制器称之为访问控制器(通常意义上我们所说的控制器就是指访问控制器)。 例如,我们访问一个URL地址: ~~~ http://tp5.com/index/index/hello ~~~ 本文档的所有示例都以tp5.com为应用测试域名,请首先配置vhost指向tp5的public目录(如不清楚请参考快速入门教程)。 实际上访问的是index模块下的Index控制器类的hello方法(在没有定义任何路由的情况下),Index控制器对应的类就是app\index\controller\Index(为什么控制器类名需要这样命名后面命名空间部分会详细描述),完成上面的URL访问,只需要定义如下的控制器类,看起来非常简单: ~~~ <?php namespace app\index\controller; class Index { public function hello() { return 'hello,world'; } } ~~~ 然后保存到目录: ~~~ application/index/controller/Index.php ~~~ 现在你可以正式测试前面提到的URL地址了。 ThinkPHP5的命名规范遵循PSR-2规范,并且约定了以下规则: 1. 目录名统一使用小写+下划线; 2. 类名使用驼峰(首字母大写)命名; 3. 类文件名和类名规范一致,并使用.php文件后缀; 4. 类的方法使用驼峰(首字母小写)命名; 5. 一个文件中只对应一个类; 特别强调:模块名作为目录作用强制使用小写和下划线规范 遵循命名规范的目的是为了让框架可以根据类的命名空间快速定位类文件的位置,从而实现自动加载,这也是PSR-4规范的要求。 #### 命名空间 现在来分析下控制器的类名为什么是app\index\controller\Index而不是Index,首先就是要明白命名空间的概念。PHP从5.3版本开始引入命名空间的概念,其主要作用是确保类名不会冲突,因为在一个应用中,出现相同的类名的几率非常之大,并且你很难保证引入的第三方类库不冲突,而有了命名空间后,相当于给自己的类加了一个门牌号一样,一个类的组成包括: > 类的组成 = 根命名空间+子命名空间(可选)+类名 这样即使是相同的类名,只要在不同的命名空间下面就属于完全不同的类,所以下面的类都是不同的类库: ~~~ app\index\controller\Index app\admin\controller\Index app\controller\Index ~~~ 而当使用下面的代码实例化一个Index类的时候, ~~~ $controller = new Index(); ~~~ 系统其实并不知道你要实例化的是哪个类库,所以首先就会从当前文件所在的命名空间去实例化Index类,但这样经常会产生混淆,所以合理的办法是明确告诉系统你实例化的是哪个具体的类,通常我们会使用use来引入一个命名空间类库,例如: ~~~ use app\admin\controller\Index; $controller = new Index(); ~~~ 这个时候就会明确当前实例化的是app\admin\controller\Index类,而不会是app\index\controller\Index类或者app\controller\Index类。 在不使用use引入的情况下,可以直接使用完整的命名空间来实例化(但并不建议,完全不必担心use过多的类库会带来性能问题) ~~~ $controller = new \app\admin\controller\Index(); ~~~ > 完整命名空间实例化的时候必须加上开头的\表示从根命名空间开始。 命名空间的根命名是可以设置起始路径的(严格来说,不仅是根命名可以设置,比如有些扩展就可以单独设置自己的命名空间的对应路径,composer通常是这么设计的),系统默认设置了下面三个根命名: |根命名 |描述 |类库起始目录| |--|--|--| |think |系统核心类库 |thinkphp/library/think| |traits |系统Trait类库 |thinkphp/library/traits| |app |应用类库 |application| 按照PSR-4的规范,子命名空间和目录必须是一一对应的,而且大小写一致。最后的类名部分实际对应的是一个和类名一致(包括大小写)的文件,保持一致规范约束的目的是为了实现类的自动加载(ThinkPHP开发过程中一定要明白大小写是严格区分的,即使是在windows下面)。 综上分析,前面的类库对应的类文件分别是: ~~~ application/index/controller/Index.php application/admin/controller/Index.php application/controller/Index.php ~~~ 现在我们来回答为什么控制器类的名称是`app\index\controller\Index`,这是ThinkPHP框架制定的规范,app是应用类库的根命名空间,也就是所有的应用类库都应该用app作为根命名空间定义。index是表示模块目录,controller表示的是控制器(确切的说是访问控制器)目录,Index是实际的控制器类名,所以要表示index模块的Index控制器类,使用的就是`app\index\controller\Index`,如果是admin模块的Index控制器类,使用的就是`app\admin\controller\Index`类,如果使用的是单一模块的话,那么Index控制器类就变成了`app\controller\Index`,现在明白了么? 核心类库都是以think开头的命名空间,应用类库都是以`app`开头的命名空间,核心类库一般也不需要更改命名空间,但应用类库是可以单独定义命名空间的。