本講主要是了解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`開頭的命名空間,核心類庫一般也不需要更改命名空間,但應用類庫是可以單獨定義命名空間的。