本講的內容主要是如何根據不同的請求進行響應輸出,主要包括:
[TOC]
> 響應(Response)對象用于動態響應客戶端請求,控制發送給用戶的信息。通常用于輸出數據給客戶端或者瀏覽器。
ThinkPHP5的Response響應對象由`think\Response`類或者子類完成,ThinkPHP的`App::run()`方法的返回值是一個`Response`對象實例,最終會調用`Response對象`的`send方法`完成輸出。
#### 自動輸出
大多數情況,我們不需要關注`Response對象`本身,只需要在控制器的操作方法中返回數據即可,系統會根據`default_return_type`和`default_ajax_return`配置決定響應輸出的類型。
默認的自動響應輸出會自動判斷是否AJAX請求,如果是的話會自動輸出default_ajax_return配置的輸出類型。
~~~
<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return $data;
}
}
~~~
由于默認是輸出Html輸出,所以訪問頁面輸出結果為:

修改配置文件,添加:
~~~
// 默認輸出類型
'default_return_type' => 'json',
~~~
再次訪問的輸出結果為:

修改輸出類型為xml:
~~~
// 默認輸出類型
'default_return_type' => 'xml',
~~~
則輸出結果變成:

> 現在明白為什么控制器的操作方法中不要直接echo輸出,而要使用return返回了么。
#### 手動輸出
> 在必要的時候,可以手動控制輸出類型和參數(也是建議的方式),這種方式較為靈活。
例如如果需要指定json輸出類型,可以使用下面的方式:
~~~
<?php
namespace app\index\controller;
use think\Response;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return Response::create($data,'json');
}
}
~~~
或者直接使用系統提供的助手函數輸出json:
~~~
<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return json($data);
}
}
~~~
使用助手函數不受配置參數設置的影響,頁面輸出的結果為:
~~~
{"name":"thinkphp","status":"1"}
~~~
默認的情況下發送的http狀態碼是200,如果需要返回其它的狀態碼,可以使用:
~~~
<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return json($data, 201);
}
}
~~~
或者發送更多的響應頭信息:
~~~
<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return json($data, 201, ['Cache-control' => 'no-cache,must-revalidate']);
}
}
~~~
也支持使用下面的鏈式調用的方式:
~~~
<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return json($data)->code(201)->header(['Cache-control' => 'no-cache,must-revalidate']);
}
}
~~~
默認支持的輸出類型包括:
|輸出類型 |快捷方法 |對應Response類|
|--|--|--|
|HTML輸出 |response |\think\Response|
|渲染模板輸出 |view |\think\response\View|
|JSON輸出| json |\think\response\Json|
|JSONP輸出| jsonp |\think\response\Jsonp|
|XML輸出 |xml |\think\response\Xml|
|頁面重定向 |redirect |\think\response\Redirect|
所以,同樣的可以使用xml方法輸出XML數據類型:
~~~
<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = ['name' => 'thinkphp', 'status' => '1'];
return xml($data, 201);
}
}
~~~
如果你只需要輸出一個html格式的內容,可以直接使用
~~~
<?php
namespace app\index\controller;
class Index
{
public function hello()
{
$data = 'Hello,ThinkPHP!';
return response($data);
}
}
~~~
每一種輸出類型其實對應了一個不同的Response子類(response()函數對應的是Response基類),也可以在應用中自定義Response子類滿足特殊需求的輸出。
這些助手函數的返回值都是Response類或者子類的對象實例,所以后續可以調用Response基類或者當前子類的相關方法,后面我們會講解相關方法。
關于view助手函數的詳細用法我們還會在下一講中進行更詳細的講解。
#### 設置數據
Response基類提供了data方法用于設置響應數據。
~~~
response()->data($data);
json()->data($data);
~~~
不過需要注意的是data方法設置的只是原始數據,并不一定是最終的輸出數據,最終的響應輸出數據是會根據當前的Response響應類型做自動轉換的,例如:
~~~
json()->data($data);
~~~
最終的輸出數據就是`json_encode($data)`轉換后的數據。
如果要獲取當前響應對象實例的實際輸出數據可以使用`getContent方法`。
#### 設置狀態碼
Response基類提供了code方法用于設置響應數據,但大部分情況一般我們是直接在調用助手函數的時候直接傳入狀態碼,例如:
~~~
json($data,201);
view($data,401);
~~~
或者在后面鏈式調用code方法是等效的:
~~~
json($data)->code(201);
~~~
除了redirect函數的默認返回狀態碼是302之外,其它方法沒有指定狀態碼都是返回200狀態碼。
如果要獲取當前響應對象實例的狀態碼的值,可以使用getCode方法。
#### 設置頭信息
可以使用Response類的header設置響應的頭信息
~~~
json($data)->code(201)->header(['Cache-control' => 'no-cache,must-revalidate']);
~~~
header方法支持兩種方式設置,如果傳入數組,則表示批量設置,如果傳入兩個參數,第一個參數表示頭信息名,第二個參數表示頭信息的值,例如:
~~~
// 單個設置
header('Cache-control', 'no-cache,must-revalidate');
// 批量設置
header([
'Cache-control' => 'no-cache,must-revalidate',
'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT',
]);
~~~
除了header方法之外,Response基類還提供了常用頭信息的快捷設置方法:
|方法名 |作用|
|--|--|
|lastModified |設置Last-Modified頭信息|
|expires |設置Expires頭信息|
|eTag |設置ETag頭信息|
|cacheControl |設置Cache-control頭信息|
|contentType |設置Content-Type頭信息|
除非你要清楚自己在做什么,否則不要隨便更改這些頭信息,每個Response子類都有默認的contentType信息,一般無需設置。
你可以使用`getHeader方法`獲取當前響應對象實例的頭信息。
#### 設置額外參數
有些時候,響應輸出需要設置一些額外的參數,例如:
在進行json輸出的時候需要設置json_encode方法的額外參數,jsonp輸出的時候需要設置jsonp_handler等參數,這些都可以使用options方法來進行處理,例如:
~~~
json($data)
->options('json_encode_param',JSON_PRETTY_PRINT);
~~~
也可以支持傳入數組作為參數:
~~~
jsonp($data)
->options([
'var_jsonp_handler' => 'callback',
'default_jsonp_handler' => 'jsonpReturn',
'json_encode_param' => JSON_PRETTY_PRINT,
]);
~~~
#### 重定向
可以使用redirect助手函數進行重定向
~~~
<?php
namespace app\index\controller;
class Index
{
public function hello()
{
return redirect('http://www.thinkphp.cn');
}
}
~~~
redirect函數和控制器的redirect方法的參數順序有所區別。
#### 重定向傳參
如果是站內重定向的話,可以支持URL組裝,有兩種方式組裝URL,第一種是直接使用完整地址(/打頭)
~~~
redirect('/index/index/hello/name/thinkphp');
~~~
這種方式會保持原來地址不做任何轉換,第二種方式是使用params方法配合,例如:
~~~
redirect('hello')->params(['name'=>'thinkphp']);
~~~
最終重定向的URL地址和前面的一樣的,系統內部會自動判斷并調用url(用于快速生成URL地址的助手函數)方法進行地址生成,相當于
~~~
redirect(url('hello',['name'=>'thinkphp']));
~~~
還可以支持使用with方法進行重定向隱式傳值。
~~~
<?php
namespace app\index\controller;
class Index
{
public function index()
{
return redirect('hello')->with('name','thinkphp');
}
public function hello()
{
$name = session('name');
return 'hello,'.$name.'!';
}
}
~~~
從示例可以看到重定向隱式傳值使用的是Session方式隱式傳值,并且僅在下一次請求有效,再次訪問重定向地址的時候無效。
我們訪問請求
~~~
http://www.tp5.com
~~~
會輸出:

但當我們第二次請求
http://www.tp5.com/index/index/hello
的時候,頁面輸出結果為:

#### 記住請求地址
在很多時候,我們重定向的時候需要記住當前請求地址(為了便于跳轉回來),我們可以使用`remember方法`記住重定向之前的請求地址。
下面是一個示例,我們第一次訪問index操作的時候會重定向到hello操作并記住當前請求地址,然后操作完成后到restore方法,restore方法則會自動重定向到之前記住的請求地址,完成一次重定向的回歸,回到原點!(再次刷新頁面又可以繼續執行)
~~~
<?php
namespace app\index\controller;
class Index
{
public function index()
{
// 判斷session完成標記是否存在
if (session('?complete')) {
// 刪除session
session('complete', null);
return '重定向完成,回到原點!';
} else {
// 記住當前地址并重定向
return redirect('hello')
->with('name', 'thinkphp')
->remember();
}
}
public function hello()
{
$name = session('name');
return 'hello,' . $name . '! <br/><a href="/index/index/restore">點擊回到來源地址</a>';
}
public function restore()
{
// 設置session標記完成
session('complete', true);
// 跳回之前的來源地址
return redirect()->restore();
}
}
~~~
#### 總結
目前我們已經掌握了不同類型的響應輸出以及設置,下一講的內容是專門針對模板渲染做了更深入的講解。