* * * * *
[TOC]
## 獲取請求
要通過依賴注入的方式來獲取當前 HTTP 請求的實例,你應該在控制器方法中使用?`Illuminate\Http\Request`?類型提示。當前的請求實例將通過?[服務容器](服務容器.md)?自動注入:
~~~
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* 儲存一個新用戶。
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$name = $request->input('name');
//
}
}
~~~
#### 依賴注入 & 路由參數
如果控制器方法也有輸入數據是從路由參數中傳入的,只需將路由參數置于其他依賴之后。
例如,你的路由是這樣定義的:
~~~
Route::put('user/{id}', 'UserController@update');
~~~
只要像下方一樣定義控制器方法,你就可以使用?`Illuminate\Http\Request`?類型提示了,同時獲取到路由參數?`id`:
~~~
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* 更新指定的用戶。
*
* @param Request $request
* @param string $id
* @return Response
*/
public function update(Request $request, $id)
{
//
}
}
~~~
#### 通過路由閉包獲取請求
你也可以在一個路由閉包中使用?`Illuminate\Http\Request`?類型提示。當它執行時,服務容器會自動注入當前請求到閉包中:
~~~
use Illuminate\Http\Request;
Route::get('/', function (Request $request) {
//
});
~~~
### 請求路徑 & 方法
`Illuminate\Http\Request`?的實例提供了多種方法去檢查應用程序的 HTTP 請求,Laravel 的?`Illuminate\Http\Request`?繼承了?`Symfony\Component\HttpFoundation\Request`?類。下面是該類幾個有用的方法:
#### 獲取請求路徑
`path`?方法返回請求路徑信息。所以,如果收到的請求目標地址是?`http://domain.com/foo/bar`,那么?`path`?將會返回?`foo/bar`:
~~~
$uri = $request->path();
~~~
`is`?方法可以驗證收到的請求路徑和指定規則是否匹配。使用這個方法的時候你也可以傳遞一個?`*`?字符作為通配符:
~~~
if ($request->is('admin/*')) {
//
}
~~~
#### 獲取請求的 URL
你可以使用?`url`?或?`fullUrl`?方法去獲取傳入請求的完整 URL。`url`?方法返回不帶有查詢字符串的 URL,而?`fullUrl`?方法的返回值包含查詢字符串:
~~~
// Without Query String...
$url = $request->url();
// With Query String...
$url = $request->fullUrl();
~~~
#### 獲取請求方法
對于傳入的請求?`method`?方法將返回 HTTP 的請求方式。你也可以使用?`isMethod`?方法去驗證 HTTP 的請求方式與指定規則是否相配:
~~~
$method = $request->method();
if ($request->isMethod('post')) {
//
}
~~~
### PSR-7 請求
[PSR-7 標準](http://www.php-fig.org/psr/psr-7/)制定的 HTTP 消息接口包含了請求和響應。如果你想使用一個 PSR-7 請求來代替一個 Laravel 請求,那么你首先要安裝幾個函數庫。Laravel 使用了 Symfony 的 HTTP 消息橋接組件,將原來的 Laravel 請求和響應轉換到 PSR-7 所兼容的實現:
~~~
composer require symfony/psr-http-message-bridge
composer require zendframework/zend-diactoros
~~~
安裝完這些庫后, 就可以在路由閉包或控制器中,簡單的對請求類型使用類型提示來獲取 PSR-7 的請求:
~~~
use Psr\Http\Message\ServerRequestInterface;
Route::get('/', function (ServerRequestInterface $request) {
//
});
~~~
> {tip} 如果你從路由或者控制器返回了一個 PSR-7 響應實例,那么這個實例將被自動轉換回一個 Laravel 響應實例,同時由框架顯示。
## 輸入數據的預處理和規范化
在 Laravel 的全局中間件中默認包含了?`TrimStrings`?和?`ConvertEmptyStringsToNull`?兩個中間件。這些中間件被列在?`App\Http\Kernel`?類中。它們會自動處理所有請求中傳入的字符串字段,比如將空的字符串字段轉變成?`null`值。你再也不用擔心路由和控制器中數據規范化的問題。
如果你想停用這些功能,你可以在?`App\Http\Kernel`?類的?`$middleware`?屬性中移除這些中間件。
## 獲取輸入數據
#### 獲取所有輸入數據
你可以使用?`all`?方法以?`數組`?形式獲取到所有輸入數據:
~~~
$input = $request->all();
~~~
#### 獲取指定輸入值
你可以通過?`Illuminate\Http\Request`?的實例,借助幾個簡單的方法,就可以獲取到用戶輸入的所有數據。而不需要擔心發起請求時使用了哪一種請求方式,`input`?方法通常被用來獲取用戶輸入數據:
~~~
$name = $request->input('name');
~~~
你可以給?`input`?方法的第二個參數傳入一個默認值。當請求的輸入數據不存在于此請求時,返回該默認值:
~~~
$name = $request->input('name', 'Sally');
~~~
如果傳輸表單數據中包含「數組」形式的數據,那么可以使用「點」語法來獲取數組:
~~~
$name = $request->input('products.0.name');
$names = $request->input('products.*.name');
~~~
#### 通過動態屬性獲取輸入數據
你也可以通過?`Illuminate\Http\Request`?實例的動態屬性來獲取用戶輸入的數據。例如,如果你應用程序表單中包含?`name`?字段,那么可以像這樣訪問提交的值:
~~~
$name = $request->name;
~~~
Laravel 在處理動態屬性的優先級是,先從請求的數據中查找,沒有的話再到路由參數中找。
#### 獲取 JSON 輸入信息
當你發送 JSON 請求到應用時,只要請求表頭中設置了?`Content-Type`?為 `application/json`,你就可以直接從?`Input`?方法中獲取 JSON 數據。你也可以通過 「點」語法來讀取 JSON 數組:
~~~
$name = $request->input('user.name');
~~~
#### 獲取部分輸入數據
如果你需要獲取輸入數據的子集,則可以用?`only`?和?`except`?方法。這兩個方法都接收單個?`數組`?或動態列表作為參數:
~~~
$input = $request->only(['username', 'password']);
$input = $request->only('username', 'password');
$input = $request->except(['credit_card']);
$input = $request->except('credit_card');
~~~
`only`?方法會返回所有你指定的鍵值對,即使這個鍵在輸入數據中并不存在。如果一個鍵在輸入數據中并不存在時,它對應的值是?`null`?。當你想要獲取請求中實際存在的輸入數據時,你可以使用?`intersect`?方法。
~~~
$input = $request->intersect(['username', 'password']);
~~~
#### 確定是否有輸入值
要判斷請求是否存在該數據,可以使用?`has`?方法。當數據存在 **并且** 字符串不為空時,`has`?方法就會返回?`true`:
~~~
if ($request->has('name')) {
//
}
~~~
### 舊輸入數據
Laravel 允許你將本次的輸入數據保留到下一次請求發送前。這個特性在表單驗證錯誤后重新填寫表單相當有用。但是,如果你使用了 Laravel 的?[驗證特性](表單驗證.md),你就不需要在手動實現這些方法,因為 Laravel 內置的驗證工具會自動調用他們。
#### 將輸入數據閃存至 Session
`Illuminate\Http\Request`?的?`flash`?方法會將當前輸入的數據存進?[session](Session.md)?中,因此下次用戶發送請求到應用程序時就可以使用它們:
~~~
$request->flash();
~~~
你也可以使用?`flashOnly`?和?`flashExcept`?方法將當前請求數據的子集保存到 session。這些方法對敏感信息的保護非常有用:
~~~
$request->flashOnly(['username', 'email']);
$request->flashExcept('password');
~~~
#### 閃存輸入數據到 Session 后重定向
你可能需要把輸入數據閃存到 session 并重定向到前一個頁面,這時只需要在重定向方法后加上?`withInput`?即可:
~~~
return redirect('form')->withInput();
return redirect('form')->withInput(
$request->except('password')
);
~~~
#### 獲取舊輸入數據
若要獲取上一次請求后所閃存的輸入數據,則可以使用?`Request`?實例中的?`old`?方法。`old`?方法提供一個簡便的方式從?[Session](Session.md)?取出被閃存的輸入數據:
~~~
$username = $request->old('username');
~~~
Laravel 也提供了全局輔助函數?`old`。如果你要在?[Blade 模板](Blade模板.md)?中顯示舊輸入數據,可以使用更加方便的?`old`?輔助函數。如果舊數據不存在,則返回?`null`:
~~~
<input type="text" name="username" value="{{ old('username') }}">
~~~
### Cookies
#### 從請求中獲取 Cookie 值
Laravel 框架創建的每個 cookie 都會被加密并且加上認證標識,這代表著用戶擅自更改的 cookie 都會失效。若要從此次請求獲取 cookie 值,你可以使用?`Illuminate\Http\Request`?實例中的?`cookie`?方法:
~~~
$value = $request->cookie('name');
~~~
#### 將 Cookies 附加到響應
你可以使用?`cookie`?方法附加一個 cookie 到?`Illuminate\Http\Response`?實例。有效 cookie 應該傳遞字段名稱,字段值和過期時間給這個方法:
~~~
return response('Hello World')->cookie(
'name', 'value', $minutes
);
~~~
`cookie`?方法還可以接受更多參數,只是使用頻率較低。通常作用是傳遞參數給 PHP 原生?[設置 cookie](http://php.net/manual/en/function.setcookie.php)?方法:
~~~
return response('Hello World')->cookie(
'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
);
~~~
#### 生成 Cookie 實例
如果你想要在一段時間以后生成一個可以給定?`Symfony\Component\HttpFoundation\Cookie`?的響應實例,你可以先生成 $cookie 實例,然后再指定給 response 實例,否則這個 cookie 不會被發送回客戶端:
~~~
$cookie = cookie('name', 'value', $minutes);
return response('Hello World')->cookie($cookie);
~~~
> 譯者注: 關于 Cookie,需要注意一點,默認 Laravel 創建的所有 Cookie 都是加密過的,創建未加密的 Cookie 的方法請見?[【小技巧分享】在 Laravel 中設置沒有加密的 cookie](https://laravel-china.org/topics/1758)
## 文件資源
### 獲取上傳文件
你可以使用?`Illuminate\Http\Request`?實例中的?`file`?方法獲取上傳的文件。file 方法返回的對象是?`Symfony\Component\HttpFoundation\File\UploadedFile`?類的實例,該類繼承了 PHP 的?`SplFileInfo`?類,并提供了許多和文件交互的方法:
~~~
$file = $request->file('photo');
$file = $request->photo;
~~~
你可以使用請求的?`hasFile`?方法確認上傳的文件是否存在:
~~~
if ($request->hasFile('photo')) {
//
}
~~~
#### 確認上傳的文件是否有效
除了檢查上傳的文件是否存在外,你也可以通過?`isValid`?方法驗證上傳的文件是否有效:
~~~
if ($request->file('photo')->isValid()) {
//
}
~~~
#### 文件路徑 & 擴展
`UploadedFile`?這個類也包含了訪問文件完整路徑和擴展的方法。`extension`?方法會嘗試根據文件內容猜測文件的擴展名。猜測結果可能不同于客戶端原始的擴展名:
~~~
$path = $request->photo->path();
$extension = $request->photo->extension();
~~~
#### 其它上傳文件的方法
`UploadedFile`?的實例還有許多可用的方法,可以到該對象的?[API 文檔](http://api.symfony.com/3.0/Symfony/Component/HttpFoundation/File/UploadedFile.html)?了解這些方法的詳細信息。
### 儲存上傳文件
在設置好?[文件系統](文件存儲.md)?的配置信息后,你可以使用?`UploadedFile`?的?`store`?方法把上傳文件儲存到本地磁盤,或者是亞馬遜 S3 云存儲上。
`store`?方法允許存儲文件到相對于文件系統根目錄配置的路徑。這個路徑不能包含文件名,名稱將使用 MD5 散列文件內容自動生成。
`store`?方法還接受一個可選的第二個參數,用于文件存儲到磁盤的名稱。這個方法會返回文件相對于磁盤根目錄的路徑:
~~~
$path = $request->photo->store('images');
$path = $request->photo->store('images', 's3');
~~~
如果你不想自動生成文件名,那么可以使用?`storeAs`?方法去設置路徑,文件名和磁盤名作為方法參數:
~~~
$path = $request->photo->storeAs('images', 'filename.jpg');
$path = $request->photo->storeAs('images', 'filename.jpg', 's3');
~~~
- 前言
- 翻譯說明
- 發行說明
- 升級說明
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- 請求周期
- 開發環境部署
- Homestead
- Valet
- 核心概念
- 服務容器
- 服務提供者
- Facades
- Contracts
- HTTP層
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- Session
- 表單驗證
- 前端
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全
- 用戶認證
- Passport OAuth 認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 錯誤與日志
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- 序列化
- 測試
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Scout 全文搜索
- Socialite 社會化登錄