建立響應
字串 & 陣列
使用者的每個請求無一例外得都要給予一個響應。Laravel 提供了幾種不同的響應方式。最簡單的響應是從路由或控制器中返回一個字串。Laravel 會將這個字串自動轉換為完整的 HTTP 響應。
Route::get('/', function () {
return 'Hello World';
});
除了返回字串,還可以返回一個陣列。Laravel 會將這個陣列自動轉換為 JSON 響應。
Route::get('/', function () {
return [1, 2, 3];
});
小提示:從路由或控制器中返回的 Eloquent 集合也會被自動轉換為 JSON 響應哦~
響應物件
我們一般不會只返回一個字串或者陣列。相反,我們經常返回完整的 Illuminate\Http\Response
例項或者檢視。
返回一個 Response
例項的話,允許我們自定義 HTTP 響應碼和標頭。Response
例項繼承了 Symfony\Component\HttpFoundation\Response
類,提供了大量構建 HTTP 響應的方法:
Route::get('home', function () {
return response('hello world', 200)
->header('Content-Type', 'text/plain');
});
為響應附加標頭
記住,Response
例項的大多數方法都是可以鏈式呼叫的。例如,你可以連續使用幾次 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',
]);
為響應附加 Cookie
使用 cookie
方法為響應附加 Cookie,向下面這樣:
return response($content)
->header('Content-Type', $type)
->cookie('name', 'value', $minutes);
cookie
方法還接收一些引數,不過不常用。如果要使用,只要記住,cookie
方法的簽名和原生 PHP 方法 setcookie
是一樣的:
->cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly)
Cookie & 加密
預設,Laravel 生成的所有 Cookie 都會經過加密和簽名處理,不能被客戶端修改和讀取。如果需要列出一個「白名單」,不用對名單裡的 Cookie 加密的話,就要用到 App\Http\Middleware\EncryptCookies
中介軟體的 $except
屬性,位於 app/Http/Middleware
目錄下:
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
'cookie_name',
];
重定向
重定向響應是 Illuminate\Http\RedirectResponse
例項,並且包含重定向所需的正確標頭資訊。有幾種生成 RedirectResponse
例項的方式。最簡單的是使用全域性 redirect
輔助函式:
Route::get('dashboard', function () {
return redirect('home/dashboard');
});
有時需要重定向到之前地址,比如當提交表單無效時。這時可以使用 back
輔助函式。因為這個函式使用了 Session,所以要保證呼叫 call
函式的路由使用了 web
中介軟體組或者是應用了所有的 Session 相關中介軟體:
Route::post('user/profile', function () {
// Validate the request...
return back()->withInput();
});
重定向到命名路由
直接呼叫 redirect()
方法會返回一個 Illuminate\Routing\Redirector
例項,你就可以使用這個例項上的方法了。例如,你可以使用 route
方法產生一個到命名路由的 RedirectResponse
例項:
return redirect()->route('login');
如果路由包含引數,給 route
方法傳遞第二個引數指定:
// For a route with the following URI: profile/{id}
return redirect()->route('profile', ['id' => 1]);
使用 Eloquent Model 填充路由引數
如果你重定向的那個路由包含一個叫 id
的路由引數,那麼可以向 route
方法直接傳遞 Eloquent Model 例項。ID 值會被自動解析:
// For a route with the following URI: profile/{id}
return redirect()->route('profile', [$user]);
如果路由引數使用的不是 id
,而是其他欄位名(比如 email
),那這個時候就需要在 Eloquent Model 設定 getRouteKey
方法了,告訴 Laravel 從 Eloquent Model 中解析 email
這個欄位值給路由引數:
/**
* Get the value of the model's route key.
*
* @return mixed
*/
public function getRouteKey()
{
return $this->email;
}
重定向到控制器 Action
給 action
方法傳遞控制器和 action 名就可以重定向到某個控制器 action。記住,你無需指定包含完整名稱空間的控制器類名,只需指定 App\Http\Controllers
後面那部分的內容,這是在 Laravel 的 RouteServiceProvider
中設定的:
return redirect()->action('HomeController@index');
如果路由包含引數,給 action
方法傳遞第二個引數指定:
return redirect()->route(
'UserController@profile', ['id' => 1]
);
重定向時攜帶 Session 快閃記憶體資料
重定向到一個新 URL,並且快閃記憶體資料到 Session 經常同時進行。比如,我們在成功操作某一個動作後,返回一條提示操作成功的訊息。為了方便,你可以在 RedirectResponse
例項上直接使用 with
方法將訊息快閃記憶體到 Session 中,一行程式碼搞定!
Route::post('user/profile', function () {
// Update the user's profile...
return redirect('dashboard')->with('status', 'Profile updated!');
});
重定向後,就可以從 Session 中獲得快閃記憶體訊息了。下面以 Blade 模板檔案為例,展示訊息內容:
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
其他響應型別
response
輔助函式可以產生其他型別的響應例項。當以無參的形式呼叫 response
函式的時候,也就是 response()
——它會返回一個實現了 Illuminate\Contracts\Routing\ResponseFactory
契約的例項。在這個契約裡提供了一些有用的產生響應的方法。
檢視響應
如果需要指定響應的狀態碼、標頭,而且還要返回一個檢視,可以使用 view
方法:
return response()
->view('hello', $data, 200)
->header('Content-Type', $type);
當然,如果不用自定義響應狀態碼或者標頭,直接返回檢視,那麼用全域性 view
輔助函式完全 OK。
JSON 響應
json
方法會自動設定 Content-Type
標頭為 application/json
,並且使用 PHP json_encode
函式將陣列轉換為 JSON 資料:
return response()->json([
'name' => 'Abigail',
'state' => 'CA'
]);
如果需要建立一個 JSONP 響應,可以讓 json
方法結合 withCallback
方法使用:
return response()
->json(['name' => 'Abigail', 'state' => 'CA'])
->withCallback($request->input('callback'));
檔案下載
download
方法強制瀏覽器下載指定路徑下的檔案。該方法接收第二個引數作為檔名(終端使用者看到的檔名)。最後,你可以傳遞第三個包含標頭資訊的陣列引數:
return response()->download($pathToFile);
return response()->download($pathToFile, $name, $headers);
return response()->download($pathToFile)->deleteFileAfterSend(true);
注意!管理檔案下載的 Symfony HttpFoundation 需要下載的檔案具有 ASCII 檔名。
檔案響應
file
方法用來強制顯示檔案,比如圖片和 PDF 檔案(而不是下載)。該方法的第一個引數是檔案路徑,第二個引數是包含標頭資訊的陣列:
return response()->file($pathToFile);
return response()->file($pathToFile, $headers);
響應巨集
可以使用 Response
門面的 macro
方法,自定義可以在各種路由和控制器中重複使用的響應,這就是「響應巨集」。例如,在服務提供者的 boot
方法裡設定我們們的響應巨集:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Response;
class ResponseMacroServiceProvider extends ServiceProvider
{
/**
* Register the application's response macros.
*
* @return void
*/
public function boot()
{
Response::macro('caps', function ($value) {
return Response::make(strtoupper($value));
});
}
}
macro
函式的第一個引數是巨集的名字,第二個引數是閉包。巨集的閉包會在呼叫 response
輔助函式時候被執行,或者是從 ResponseFactory
的實現呼叫巨集的時候被執行。
return response()->caps('foo');
本作品採用《CC 協議》,轉載必須註明作者和本文連結