## 練習1:Hello,ThinkPHP
>[info] 任務:在安裝完成后來完成第一個實例代碼,要求運行后顯示`Hello,ThinkPHP!`。
### 實現一:路由實現
針對這個需求的最簡單實現,是在路由定義文件(`route/route.php`)開頭添加如下代碼:
~~~
Route::get('/', function () {
return 'Hello,ThinkPHP!';
});
~~~
然后直接訪問(這里使用了上一個練習的內容提到的`Vhost`訪問)
~~~
http://tp5.com
~~~
頁面輸出:
~~~
Hello,ThinkPHP!
~~~
是不是很簡單?直接通過路由定義返回頁面輸出內容(更多的路由用法我們后面還會陸續提到,暫且不表)。接下來,我們來看第二種實現代碼,通過標準的控制器來實現。
### 實現二:控制器實現
進入`CMD`命令行,切換到應用根目錄(也就是`tp5`目錄),執行下面的指令:
~~~
php think make:controller index/Hello --plain
~~~
會自動生成一個控制器文件,位于:
~~~
application/index/controller/Hello.php
~~~
在編輯器打開,可以看到已經生成了一個空的控制器(類)文件
~~~
<?php
namespace app\index\controller;
use think\Controller;
class Hello extends Controller
{
//
}
~~~
> 后面再提到控制器的時候,你的第一反應就是這個`controller`目錄下面的某個類,而且從類名就能直觀看出控制器名,從命名空間可以找到所在位置。
我們在控制器類里面添加一個`index`方法(必須使用`public`類型,一般我們稱為操作方法,它是URL訪問的最小單元),內容如下:
~~~
<?php
namespace app\index\controller;
use think\Controller;
class Hello extends Controller
{
// 顯示歡迎頁面
public function index()
{
return 'Hello,ThinkPHP!';
}
}
~~~
> 今后提到控制器的某個操作,你的第一反應就是去找這個控制器下面的某個方法。
然后我們直接在瀏覽器中訪問
~~~
http://tp5.com/index/hello
~~~
頁面輸出:
~~~
Hello,ThinkPHP!
~~~
至此,我們完成了一個標準的控制器輸出`Hello,ThinkPHP`的實現代碼。
## 拓展討論
### 為何用`return`而不用`echo`
我們看到控制器的操作方法都是直接`return`的,而沒有使用我們習慣的`echo`方法輸出。你會發現使用`echo`輸出的話,最終的結果其實是一樣的,但為什么不建議使用呢?
確實,如果你要輸出的數據本身就是字符串的話,使用`echo`的結果是一樣的,但ThinkPHP的控制器操作方法支持不同的響應輸出(甚至需要設置不同的頭信息),對于不同的響應輸出會調用不同的`Response`子類,例如`JSON`、`XML`等,你可以直接`return`一個數組或者對象數據,然后交給`Response`來處理轉換,甚至你可以直接return一個`Response`對象。還有一種情況是,你可以統一使用系統提供的鉤子對響應輸出進行額外的處理,而如果你使用了`echo`直接輸出,將無法享受這些功能特性。
>[info] 關于更多的`Response`響應處理的知識,我們后面還會陸續提到,暫且不用深究,但請保持操作方法統一`return`的習慣(除非在操作方法中間進行調試的時候可以使用`echo`或者`dump`)。
### 更優雅的URL
是否覺得
~~~
http://tp5.com/index/hello
~~~
這個訪問地址有點太長了,似乎不夠優雅,沒關系,我們馬上來改進下。
打開路由定義文件`route/route.php`,添加一行代碼如下:
~~~
Route::get('hello','Hello/index');
~~~
現在你可以優雅的訪問
~~~
http://tp5.com/hello
~~~
輸出同樣的內容。
### 添加URL變量
我們希望歡迎頁面能顯示輸入的名稱,而不是ThinkPHP,就需要用到URL變量,我們分別針對上述兩種實現來進行調整。
如果是第一種,我們修改路由定義如下:
~~~
Route::get('hello/:name', function ($name) {
return 'Hello,' . $name . '!';
});
~~~
>[info] 你暫時不用深究路由傳遞參數的原理,你只需要記得使用`:name`就表示URL中輸入的變量,然后可以在閉包中調用該同名變量。
直接訪問
~~~
http://tp5.com/hello/張三
~~~
頁面輸出結果:
~~~
Hello,張三!
~~~
你可以嘗試更改URL地址`hello`后面的名稱來查看輸出結果。
如果是第二種實現,首先把路由定義改成
~~~
Route::get('hello/:name','Hello/index');
~~~
然后對`Hello`控制器類的`index`方法稍加調整。
~~~
<?php
namespace app\index\controller;
use think\Controller;
class Hello extends Controller
{
// 顯示歡迎頁面
public function index($name='ThinkPHP')
{
return 'Hello,' . $name . !';
}
}
~~~
>[info] 沒有比這更神奇的事情了,路由地址中的變量`name`可以很神奇的傳遞到`index`方法中。
直接訪問
~~~
http://tp5.com/hello/李四
~~~
頁面輸出結果:
~~~
Hello,李四!
~~~
### 添加類庫后綴
為了盡量避免關鍵字的沖突,我們可以統一開啟類庫后綴功能,在應用根目錄下的`config`目錄下找到`app.php`文件,打開后更改下面的配置參數:
~~~
// 開啟應用類庫后綴
'class_suffix' => true,
~~~
開啟后,你所有的類庫都要統一加上你的目錄名稱(首字母大寫)作為類庫名的后綴(同時千萬別忘了,文件名也要同時調整成和類名一樣),例如:
~~~
<?php
namespace app\index\controller;
use think\Controller;
class HelloController extends Controller
{
// 顯示歡迎頁面
public function index()
{
return 'Hello,ThinkPHP!';
}
}
~~~
在你需要創建一個新控制器的時候,可以使用下面的命令:
~~~
php think make:controller index/TestController --plain
~~~
會自動生成一個控制器文件,位于:
~~~
application/index/controller/TestController.php
~~~
>[danger] 后面的練習如果沒有特殊說明,都不開啟應用類庫后綴。