* * * * *
[TOC]
## 創建響應
#### 字符串 & 數組
所有路由和控制器 都會返回一個響應并發送給用戶的瀏覽器。Laravel 提供了幾種不同的方式來返回響應。最基本的響應就是從路由或控制器返回一個字符串。框架會自動將字符串轉換為一個完整的 HTTP 響應:
~~~
Route::get('/', function () {
return 'Hello World';
});
~~~
除了從路由和控制器返回字符串之外,還可以返回數組。框架會自動將數組轉為 JSON 響應。
~~~
Route::get('/', function () {
return [1, 2, 3];
});
~~~
> {tip} 你還可以從路由或控制器中直接返回?[Eloquent 集合](http://www.hmoore.net/tonyyu/laravel_5_6/786274)?,它們會自動轉為 JSON 響應。
#### 響應對象
一般來說,你不會只從路由行為返回簡單的字符串或數組。你也許會返回完整的?`Illuminate\Http\Response`?實例或[視圖](http://www.hmoore.net/tonyyu/laravel_5_6/786178)。
返回完整的?`Response`?實例允許你自定義響應的 HTTP 狀態碼和響應頭信息。`Response`?實例繼承自?`Symfony\Component\HttpFoundation\Response`?類,該類提供了各種構建 HTTP 響應的方法:
~~~
Route::get('home', function () {
return response('Hello World', 200)
->header('Content-Type', 'text/plain');
});
~~~
#### 為響應增加頭信息
大部分的響應方法都是可鏈式調用的,使得創建響應實例的過程更具可讀性。例如,你可以在響應返回給用戶前使用?`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`?方法輕松地將為響應增加 Cookies。例如,你可以像這樣使用?`cookie`?方法生成一個 cookie 并輕松地將其附加到響應上:
~~~
return response($content)
->header('Content-Type', $type)
->cookie('name', 'value', $minutes);
~~~
`cookie`?方法還接受一些不太頻繁使用的參數。通常,這些參數與原生 PHP 的?[setcookie](https://secure.php.net/manual/en/function.setcookie.php)?方法的參數有著相同的目的和含義:
~~~
->cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly)
~~~
或者,您可以使用?`Cookie`?Facade 「排隊」,?`Cookie`?以附加到應用程序的傳出響應。?`queue`?方法接受一個?`Cookie`?實例或創建?`Cookie`?實例所需的參數。 這些 cookie 在發送到瀏覽器之前會附加到傳出響應中:
~~~
Cookie::queue(Cookie::make('name', 'value', $minutes));
Cookie::queue('name', 'value', $minutes);
~~~
#### Cookies 和 加密
默認情況下,Laravel 生成的所有 Cookie 都是經過加密和簽名,因此不能被客戶端修改或讀取。 如果你想要應用程序生成的部分 Cookie 不被加密,那么可以使用在?`app/Http/Middleware`?目錄中?`App\Http\Middleware\EncryptCookies`中間件的?`$except`?屬性:
~~~
/**
* 不需要加密的 Cookie 名稱。
*
* @var array
*/
protected $except = [
'cookie_name',
];
~~~
## 重定向
重定向響應是?`Illuminate\Http\RedirectResponse`?類的實例,并且包含用戶需要重定向至另一個 URL 所需的頭信息。Laravel 提供了幾種方法用于生成?`RedirectResponse`?實例。其中最簡單的方法是使用全局輔助函數?`redirect`:
~~~
Route::get('dashboard', function () {
return redirect('home/dashboard');
});
~~~
有時候你可能希望將用戶重定向到之前的位置,比如提交的表單無效時。這時你可以使用全局輔助函數?`back`?來執行此操作。由于這個功能利用了?[Session](http://www.hmoore.net/tonyyu/laravel_5_6/786180),請確保調用?`back`?函數的路由使用?`web`?中間件組或所有 Session 中間件:
~~~
Route::post('user/profile', function () {
// Validate the request...
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 模型填充參數
如果你要重定向到使用從 Eloquent 模型填充「ID」參數的路由,可以簡單地傳遞模型本身。ID 會被自動提取:
~~~
// 對于此路由: profile/{id}
return redirect()->route('profile', [$user]);
~~~
如果要自定義路由參數中的值,那么應該覆蓋 Eloquent 模型里面的?`getRouteKey`?方法:
~~~
/**
* 獲取模型的路由鍵.
*
* @return mixed
*/
public function getRouteKey()
{
return $this->slug;
}
~~~
### 重定向至控制器行為
你可能需要生成重定向到?[控制器行為](http://www.hmoore.net/tonyyu/laravel_5_6/786156)?的響應。為此,你要將控制器和行為名稱傳遞給?`action`?方法來實現。另外,你不一定要為控制器指定完整的命名空間,因為 Laravel 的?`RouteServiceProvider`?會自動設置基本的控制器命名空間:
~~~
return redirect()->action('HomeController@index');
~~~
如果你的控制器路由需要參數,你可以將它們作為第二個參數傳遞給?`action`?方法:
~~~
return redirect()->action(
'UserController@profile', ['id' => 1]
);
~~~
### 重定向到外部域
有時您可能需要重定向到應用程序之外的域名。 您可以通過調用?`away`?方法來實現,它會創建一個?`RedirectResponse`?而不需要任何額外的URL 編碼,驗證或認證:
~~~
return redirect()->away('https://www.google.com');
~~~
### 重定向并使用閃存的 Session 數據
通常,重定向到新的 URL 的同時會將?[數據閃存到 Session](http://www.hmoore.net/tonyyu/laravel_5_6/786180#_164)。并且成功執行將信息閃存到 Seesion 后才算完成此操作。方便起見,你可以創建一個?`RedirectResponse`?的實例并鏈式調用?`with`?方法將數據閃存在 Session 中:
~~~
Route::post('user/profile', function () {
// 更新用戶的信息...
return redirect('dashboard')->with('status', 'Profile updated!');
});
~~~
用戶重定向后,你可以從?[session](http://www.hmoore.net/tonyyu/laravel_5_6/786180)?中讀取閃存的信息。例如,使用?[Blade 語法](http://www.hmoore.net/tonyyu/laravel_5_6/786198):
~~~
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
~~~
## 其他響應類型
使用輔助函數?`response`?可以用來生成其他類型的響應實例。當不帶參數調用輔助函數?`response`?時,會返回?`Illuminate\Contracts\Routing\ResponseFactory`?契約 的實例。 契約提供了幾種輔助生成響應的方法。
### 視圖響應
如果你需要控制響應的狀態和標題,還需要返回?[視圖](http://www.hmoore.net/tonyyu/laravel_5_6/786178)?作為響應的內容,則應使用?`view`?方法:
~~~
return response()
->view('hello', $data, 200)
->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`?方法并與?`withCallback`?方法配合使用:
~~~
return response()
->json(['name' => 'Abigail', 'state' => 'CA'])
->withCallback($request->input('callback'));
~~~
### 文件下載
`download`?方法可以用來生成強制用戶瀏覽器下載指定路徑文件的響應。`download`?方法的第二個參數接受一個文件名,它將作為用戶下載的時所看見的文件名。最后,你可以傳遞一個 HTTP 響應頭數組最為該方法的第三個參數:
~~~
return response()->download($pathToFile);
return response()->download($pathToFile, $name, $headers);
return response()->download($pathToFile)->deleteFileAfterSend(true);
~~~
> {note} 管理文件下載的擴展包 Symfony HttpFoundation,要求下載文件名必須是 ASCII 編碼的。
#### 流式下載
有時,您可能希望將給定操作的字符串響應轉換為可下載的響應,而無需將操作的內容寫入磁盤。 你可以在這個場景中使用?`streamDownload`?方法。 此方法接受回調,文件名和可選的標題數組作為其參數:
~~~
return response()->streamDownload(function () {
echo GitHub::api('repo')
->contents()
->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme.md');
~~~
### 文件響應
`file`?方法可以直接在用戶瀏覽器中顯示文件(不是發起下載),例如圖像或者 PDF。此方法接受文件的路徑作為其第一個參數和頭信息數組作為其第二個參數:
~~~
return response()->file($pathToFile);
return response()->file($pathToFile, $headers);
~~~
## 響應宏
如果要定義可以在各種路由和控制器中重復使用的自定義響應,可以在?`Response`?Facade 上使用?`macro`?方法。例如,你可以在?[服務提供器](http://www.hmoore.net/tonyyu/laravel_5_6/786057)?的?`boot`?方法中這樣寫:
~~~
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Response;
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');
~~~
- 前言
- 翻譯說明
- 發行說明
- 升級指南
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- Homestead
- Valet
- 部署
- 核心架構
- 請求周期
- 服務容器
- 服務提供者
- Facades
- Contracts
- 基礎功能
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- URL
- Session
- 表單驗證
- 錯誤
- 日志
- 前端開發
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全相關
- 用戶認證
- Passport OAuth 認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- API 資源
- 序列化
- 測試相關
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Horizon
- Scout 全文搜索
- Socialite 社會化登錄