9.5 KiB
請求物件
請求物件(Request)
是完全基於 PSR-7 標準實現的,由 hyperf/http-message 元件提供實現支援。
注意 PSR-7 標準為
請求(Request)
進行了immutable 機制
的設計,所有以with
開頭的方法的返回值都是一個新物件,不會修改原物件的值
安裝
該元件完全獨立,適用於任何一個框架專案。
composer require hyperf/http-message
如用於其它框架專案則僅支援 PSR-7 提供的 API,具體可直接查閱 PSR-7 的相關規範,該文件所描述的使用方式僅限於使用 Hyperf 時的用法。
獲得請求物件
可以通過容器注入 Hyperf\HttpServer\Contract\RequestInterface
獲得 對應的 Hyperf\HttpServer\Request
,實際注入的物件為一個代理物件,代理的物件為每個請求的 PSR-7 請求物件(Request)
,也就意味著僅可在 onRequest
生命週期內可獲得此物件,下面是一個獲取示例:
declare(strict_types=1);
namespace App\Controller;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\AutoController;
/**
* @AutoController()
*/
class IndexController
{
public function info(RequestInterface $request)
{
// ...
}
}
依賴注入與引數
如果希望通過控制器方法引數獲取路由引數,可以在依賴項之後列出對應的引數,框架會自動將對應的引數注入到方法引數內,比如您的路由是這樣定義的:
// 註解方式
/**
* @GetMapping(path="/user/{id:\d+}")
*/
// 配置方式
use Hyperf\HttpServer\Router\Router;
Router::addRoute(['GET', 'HEAD'], '/user/{id:\d+}', [\App\Controller\IndexController::class, 'user']);
則可以通過在方法引數上宣告 $id
引數獲得 Query
引數 id
,如下所示:
declare(strict_types=1);
namespace App\Controller;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\AutoController;
/**
* @AutoController()
*/
class IndexController
{
public function info(RequestInterface $request, int $id)
{
// ...
}
}
除了可以通過依賴注入獲取路由引數,還可以通過 route
方法獲取,如下所示:
declare(strict_types=1);
namespace App\Controller;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\AutoController;
/**
* @AutoController()
*/
class IndexController
{
public function info(RequestInterface $request)
{
// 存在則返回,不存在則返回預設值 null
$id = $request->route('id');
// 存在則返回,不存在則返回預設值 0
$id = $request->route('id', 0);
// ...
}
}
請求路徑 & 方法
Hyperf\HttpServer\Contract\RequestInterface
除了使用 PSR-7 標準定義的 APIs
之外,還提供了多種方法來檢查請求,下面我們提供一些方法的示例:
獲取請求路徑
path()
方法返回請求的路徑資訊。也就是說,如果傳入的請求的目標地址是 http://domain.com/foo/bar?baz=1
,那麼 path()
將會返回 foo/bar
:
$uri = $request->path();
is(...$patterns)
方法可以驗證傳入的請求路徑和指定規則是否匹配。使用這個方法的時,你也可以傳遞一個 *
字元作為萬用字元:
if ($request->is('user/*')) {
// ...
}
獲取請求的 URL
你可以使用 url()
或 fullUrl()
方法去獲取傳入請求的完整 URL
。url()
方法返回不帶有 Query 引數
的 URL
,而 fullUrl()
方法的返回值包含 Query 引數
:
// 沒有查詢引數
$url = $request->url();
// 帶上查詢引數
$url = $request->fullUrl();
獲取請求方法
getMethod()
方法將返回 HTTP
的請求方法。你也可以使用 isMethod(string $method)
方法去驗證 HTTP
的請求方法與指定規則是否匹配:
$method = $request->getMethod();
if ($request->isMethod('post')) {
// ...
}
PSR-7 請求及方法
hyperf/http-message 元件本身是一個實現了 PSR-7 標準的元件,相關方法都可以通過注入的 請求物件(Request)
來呼叫。
如果注入時宣告為 PSR-7 標準的 Psr\Http\Message\ServerRequestInterface
介面,則框架會自動轉換為等同於 Hyperf\HttpServer\Contract\RequestInterface
的 Hyperf\HttpServer\Request
物件。
建議使用
Hyperf\HttpServer\Contract\RequestInterface
來注入,這樣可獲得 IDE 對專屬方法的自動完成提醒支援。
輸入預處理 & 規範化
獲取輸入
獲取所有輸入
您可以使用 all()
方法以 陣列
形式獲取到所有輸入資料:
$all = $request->all();
獲取指定輸入值
通過 input(string $key, $default = null)
和 inputs(array $keys, $default = null): array
獲取 一個
或 多個
任意形式的輸入值:
// 存在則返回,不存在則返回 null
$name = $request->input('name');
// 存在則返回,不存在則返回預設值 Hyperf
$name = $request->input('name', 'Hyperf');
如果傳輸表單資料中包含「陣列」形式的資料,那麼可以使用「點」語法來獲取陣列:
$name = $request->input('products.0.name');
$names = $request->input('products.*.name');
從查詢字串獲取輸入
使用 input
, inputs
方法可以從整個請求中獲取輸入資料(包括 Query 引數
),而 query(?string $key = null, $default = null)
方法可以只從查詢字串中獲取輸入資料:
// 存在則返回,不存在則返回 null
$name = $request->query('name');
// 存在則返回,不存在則返回預設值 Hyperf
$name = $request->query('name', 'Hyperf');
// 不傳遞引數則以關聯陣列的形式返回所有 Query 引數
$name = $request->query();
獲取 JSON
輸入資訊
如果請求的 Body
資料格式是 JSON
,則只要 請求物件(Request)
的 Content-Type
Header 值
正確設定為 application/json
,就可以通過 input(string $key, $default = null)
方法訪問 JSON
資料,你甚至可以使用 「點」語法來讀取 JSON
陣列:
// 存在則返回,不存在則返回 null
$name = $request->input('user.name');
// 存在則返回,不存在則返回預設值 Hyperf
$name = $request->input('user.name', 'Hyperf');
// 以陣列形式返回所有 Json 資料
$name = $request->all();
確定是否存在輸入值
要判斷請求是否存在某個值,可以使用 has($keys)
方法。如果請求中存在該值則返回 true
,不存在則返回 false
,$keys
可以傳遞一個字串,或傳遞一個數組包含多個字串,只有全部存在才會返回 true
:
// 僅判斷單個值
if ($request->has('name')) {
// ...
}
// 同時判斷多個值
if ($request->has(['name', 'email'])) {
// ...
}
Cookies
從請求中獲取 Cookies
使用 getCookieParams()
方法從請求中獲取所有的 Cookies
,結果會返回一個關聯陣列。
$cookies = $request->getCookieParams();
如果希望獲取某一個 Cookie
值,可通過 cookie(string $key, $default = null)
方法來獲取對應的值:
// 存在則返回,不存在則返回 null
$name = $request->cookie('name');
// 存在則返回,不存在則返回預設值 Hyperf
$name = $request->cookie('name', 'Hyperf');
檔案
獲取上傳檔案
你可以使用 file(string $key, $default): ?Hyperf\HttpMessage\Upload\UploadedFile
方法從請求中獲取上傳的檔案物件。如果上傳的檔案存在則該方法返回一個 Hyperf\HttpMessage\Upload\UploadedFile
類的例項,該類繼承了 PHP
的 SplFileInfo
類的同時也提供了各種與檔案互動的方法:
// 存在則返回一個 Hyperf\HttpMessage\Upload\UploadedFile 物件,不存在則返回 null
$file = $request->file('photo');
檢查檔案是否存在
您可以使用 hasFile(string $key): bool
方法確認請求中是否存在檔案:
if ($request->hasFile('photo')) {
// ...
}
驗證成功上傳
除了檢查上傳的檔案是否存在外,您也可以通過 isValid(): bool
方法驗證上傳的檔案是否有效:
if ($request->file('photo')->isValid()) {
// ...
}
檔案路徑 & 副檔名
UploadedFile
類還包含訪問檔案的完整路徑及其副檔名方法。getExtension()
方法會根據檔案內容判斷檔案的副檔名。該副檔名可能會和客戶端提供的副檔名不同:
// 該路徑為上傳檔案的臨時路徑
$path = $request->file('photo')->getPath();
// 由於 Swoole 上傳檔案的 tmp_name 並沒有保持檔案原名,所以這個方法已重寫為獲取原檔名的字尾名
$extension = $request->file('photo')->getExtension();
儲存上傳檔案
上傳的檔案在未手動儲存之前,都是存在一個臨時位置上的,如果您沒有對該檔案進行儲存處理,則在請求結束後會從臨時位置上移除,所以我們可能需要對檔案進行持久化儲存處理,通過 moveTo(string $targetPath): void
將臨時檔案移動到 $targetPath
位置持久化儲存,程式碼示例如下:
$file = $request->file('photo');
$file->moveTo('/foo/bar.jpg');
// 通過 isMoved(): bool 方法判斷方法是否已移動
if ($file->isMoved()) {
// ...
}