HTTP 回應
基本回應
當然,所有的路由及控制器必須回傳某個類型的回應,並發送回使用者的瀏覽器。Laravel 提供了幾種不同的方法來回傳回應。最基本的回應就是從路由或控制器簡易的回傳一個字串:
Route::get('/', function () {
return 'Hello World';
});
給定的字串會被框架自動轉換成 HTTP 回應。
回應物件
但是以大部分的路由及控制器所執行的動作來說,你需要回傳完整的 Illuminate\Http\Response
實例或是一個視圖。回傳一個完整的 Response
實例時,你能夠自定回應的 HTTP 狀態碼以及標頭。Response
實例繼承了 Symfony\Component\HttpFoundation\Response
類別,其提供了很多方法建立 HTTP 回應:
use Illuminate\Http\Response;
Route::get('home', function () {
return (new Response($content, $status))
->header('Content-Type', $value);
});
為了方便起見,你可以使用輔助方法 response
:
Route::get('home', function () {
return response($content, $status)
->header('Content-Type', $value);
});
注意:有關
Response
可用方法的完整列表可以它的參照 API 文件以及 Symfony API 文件。
附加標頭至回應
請記得,大部份的回應方法是可鏈結的,讓你建立流利的回應。舉例來說,你可以在回應送出給使用者之前,使用 header
方法增加一系列的標頭至回應:
return response($content)
->header('Content-Type', $type)
->header('X-Header-One', 'Header Value')
->header('X-Header-Two', 'Header Value');
或者,你可以使用 withHeaders
方法來指定要增加至回應的標頭陣列:
return response($content)
->withHeaders([
'Content-Type' => $type,
'X-Header-One' => 'Header Value',
'X-Header-Two' => 'Header Value',
]);
附加 Cookies 至回應
透過回應實例的 cookie
輔助方法可以讓你輕鬆的附加 cookies 至回應。舉個例子,你可以使用 cookie
方法來產生 cookie 並附加至回應實例:
return response($content)
->header('Content-Type', $type)
->cookie('name', 'value');
cookie
方法可以接受額外的選擇性參數,讓你進一步自定 cookies 的屬性:
->cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly)
預設情況下,所有 Laravel 產生的 cookies 都會被加密並加上認證記號,所以無法被使用者讀取及修改。如果你想將應用程式產生的 cookies 中某個子集的加密停用,你可以使用 App\Http\Middleware\EncryptCookies
中介層的 $except
屬性:
/**
* 不需被加密的 cookies 名稱。
*
* @var array
*/
protected $except = [
'cookie_name',
];
其它回應類型
使用輔助方法 response
可以輕鬆的產生其他類型的回應實例。當你呼叫輔助方法 response
且不帶任何參數時,將會回傳 Illuminate\Contracts\Routing\ResponseFactory
contract 的實作。此 Contract 提供了一些有用的方法來產生回應。
視圖回應
如果你想要控制回應狀態碼及標頭,但是也想要回傳一個視圖作為回傳的內容時,你可以使用 view
方法:
return response()
->view('hello', $data)
->header('Content-Type', $type);
當然,如果你不需傳遞自定 HTTP 狀態碼及標頭,那麼你只需要使用全域的 view
輔助函式。
JSON 回應
json
方法會自動將標頭的 Content-Type
設定為 application/json
,並透過 PHP 的 json_encode
函式將給定的陣列轉換為 JSON:
return response()->json(['name' => 'Abigail', 'state' => 'CA']);
如果你想建立一個 JSONP 回應,你可以使用 json
方法並加上 setCallback
:
return response()
->json(['name' => 'Abigail', 'state' => 'CA'])
->setCallback($request->input('callback'));
檔案下載
download
方法可以用於產生強制讓使用者的瀏覽器下載給定路徑檔案的回應。download
方法接受檔案名稱作為方法的第二個參數,此名稱為使用者下載檔案時看見的檔案名稱。最後,你可以傳遞一個 HTTP 標頭的陣列作為第三個參數傳入該方法:
return response()->download($pathToFile);
return response()->download($pathToFile, $name, $headers);
注意:管理檔案下載的套件 Symfony HttpFoundation,要求下載檔名必須為 ASCII。
重導
重導回應是類別 Illuminate\Http\RedirectResponse
的實例,並且包含使用者要重導至另一個 URL 所需的標頭。有幾種方法可以產生 RedirectResponse
的實例。最簡單的方式就是透過全域的 redirect
輔助方法:
Route::get('dashboard', function () {
return redirect('home/dashboard');
});
有時你可能希望將使用者重導至前一個位置,例如當提交一個無效的表單之後。你可以使用全域的 back
輔助函式來達成這個目的。不過,請確保使用 back
函式的路由有使用 web
中介層群組或是套用了所有的 session 中介層:
Route::post('user/profile', function () {
// 驗證該請求...
return back()->withInput();
});
重導至命名路由
當你呼叫輔助方法 redirect
且不帶任何參數時,將會回傳 Illuminate\Routing\Redirector
的實例,你可以對該 Redirector
的實例呼叫任何的方法。舉個例子,要產生一個 RedirectResponse
到一個命名路由,你可以使用 route
方法:
return redirect()->route('login');
如果你的路由有參數,你可以將參數放進 route
方法的第二個參數:
// 針對是這樣 URI 的路由:profile/{id}
return redirect()->route('profile', ['id' => 1]);
如果你要重導至路由且路由的參數為 Eloquent 模型的「ID」,你可以直接將模型傳入,ID 將會自動被提取:
return redirect()->route('profile', [$user]);
重導至控制器行為
你可能會希望產生重導至控制器行為。要做到這一點,只需傳遞控制器及行為名稱至 action
方法。請記得,你不需要指定完整的命名空間,因為 Laravel 的 RouteServiceProvider
會自動設定預設的控制器命名空間:
return redirect()->action('HomeController@index');
當然,如果你的控制器路由需要參數的話,你可以傳遞它們至 action
方法的第二個參數:
return redirect()->action('UserController@profile', ['id' => 1]);
重導並加上快閃 Session 資料
通常重導至新的 URL 時會一併寫入快閃資料至 session。所以為了方便,你可以利用方法鏈結的方式創建一個 RedirectResponse
的實例並快閃資料至 Session。這對於在一個動作之後儲存狀態訊息相當方便:
Route::post('user/profile', function () {
// 更新使用者的個人資料...
return redirect('dashboard')->with('status', 'Profile updated!');
});
當然,在使用者重導至新的頁面後,你可以取得並顯示 session 的快閃資料。舉個例子,使用 Blade 的語法:
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
回應巨集
如果你想要定義可以不同路由和控制器重複使用的自訂回應,你可以使用 Response
facade 的 macro
方法或是 Illuminate\Contracts\Routing\ResponseFactory
的實作。
舉個例子,來自服務提供者的 boot
方法:
<?php
namespace App\Providers;
use Response;
use Illuminate\Support\ServiceProvider;
class ResponseMacroServiceProvider extends ServiceProvider
{
/**
* 提供註冊後執行的服務。
*
* @return void
*/
public function boot()
{
Response::macro('caps', function ($value) {
return Response::make(strtoupper($value));
});
}
}
macro
函式第一個參數為巨集名稱,第二個參數為閉包函式。巨集的閉包函式會在 ResponseFactory
的實作或者輔助方法 response
呼叫巨集名稱的時候被執行:
return response()->caps('foo');