# HTTP請求
- [獲取請求](#accessing-the-request)
- [請求路徑 & 方法](#request-path-and-method)
- [PSR-7 請求](#psr7-requests)
- [獲取輸入數據](#retrieving-input)
- [舊輸入數據](#old-input)
- [Cookies](#cookies)
- [文件資源](#files)
- [獲取上傳文件](#retrieving-uploaded-files)
- [儲存上傳文件](#storing-uploaded-files)
<a name="accessing-the-request"></a>
## 獲取請求
要通過依賴注入的方式來獲取當前 HTTP 請求的實例,你應該在控制器方法中使用 `Illuminate\Http\Request` 類型提示。當前的請求實例將通過 [服務容器](/docs/{{version}}/container) 自動注入:
<?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) {
//
});
<a name="request-path-and-method"></a>
### 請求路徑 & 方法
`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')) {
//
}
<a name="psr7-requests"></a>
### 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 響應實例,同時由框架顯示。
<a name="retrieving-input"></a>
## 獲取輸入數據
#### 獲取所有輸入數據
你可以使用 `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');
#### 確定是否有輸入值
要判斷請求是否存在該數據,可以使用 `has` 方法。當數據存在 **并且** 字符串不為空時,`has` 方法就會返回 `true`:
if ($request->has('name')) {
//
}
<a name="old-input"></a>
### 舊輸入數據
Laravel 允許你將本次的輸入數據保留到下一次請求發送前。這個特性在表單驗證錯誤后重新填寫表單相當有用。但是,如果你使用了 Laravel 的 [驗證特性](/docs/{{version}}/validation),你就不需要在手動實現這些方法,因為 Laravel 內置的驗證工具會自動調用他們。
#### 將輸入數據閃存至 Session
`Illuminate\Http\Request` 的 `flash` 方法會將當前輸入的數據存進 [session](/docs/{{version}}/session) 中,因此下次用戶發送請求到應用程序時就可以使用它們:
$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](/docs/{{version}}/session) 取出被閃存的輸入數據:
$username = $request->old('username');
Laravel 也提供了全局輔助函數 `old`。如果你要在 [Blade 模板](/docs/{{version}}/blade) 中顯示舊輸入數據,可以使用更加方便的 `old` 輔助函數。如果舊數據不存在,則返回 `null`:
<input type="text" name="username" value="{{ old('username') }}">
<a name="cookies"></a>
### 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://phphub.org/topics/1758)
<a name="files"></a>
### Files
<a name="retrieving-uploaded-files"></a>
### 獲取上傳文件
你可以使用 `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) 了解這些方法的詳細信息。
<a name="storing-uploaded-files"></a>
### 儲存上傳文件
在設置好 [文件系統](/docs/{{version}}/filesystem) 的配置信息后,你可以使用 `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模板
- 本地化
- Javascript與CSS
- 入門指南
- laravel-elixir
- 安全
- 用戶認證
- 用戶授權
- 重置密碼
- API授權
- 加密解密
- 哈希
- 綜合話題
- 廣播系統
- 緩存系統
- 事件系統
- 文件存儲
- 郵件發送
- 消息通知
- 隊列
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent集合
- 修改器
- 序列化
- Artisan控制臺
- Artisan 命令行
- 任務調度
- 測試
- 快速入門
- 應用程序測試
- 數據庫測試
- 模擬器
- 官方擴展包
- Cashier交易包
- Envoy 部署工具
- Passport OAuth 認證
- Scout 全文搜索
- Socialite 社交化登錄
- 附錄
- 集合
- 輔助函數
- 擴展包開發
- 交流說明