說明
獲得請求對象
webman 會自動將請求對象注入到 action 方法的第一個參數中,例如
例子
<?php
namespace app\controller;
use support\Request;
class UserController
{
public function hello(Request $request)
{
$default_name = 'webman';
// 從 get 請求裡獲得 name 參數,如果沒有傳遞 name 參數則返回 $default_name
$name = $request->get('name', $default_name);
// 向瀏覽器返回字符串
return response('hello ' . $name);
}
}
透過 $request
對象我們能獲取到請求相關的任何數據。
有時候我們想在其他類中獲取當前請求的 $request
對象,這時候我們只要使用助手函數 request()
即可;
獲得請求參數 get
獲取整個 get 陣列
$request->get();
如果請求沒有 get 參數則返回一個空的陣列。
獲取 get 陣列的某一個值
$request->get('name');
如果 get 陣列中不包含這個值則返回 null。
你也可以給 get 方法第二個參數傳遞一個默認值,如果 get 陣列中沒找到對應值則返回默認值。例如:
$request->get('name', 'tom');
獲得請求參數 post
獲取整個 post 陣列
$request->post();
如果請求沒有 post 參數則返回一個空的陣列。
獲取 post 陣列的某一個值
$request->post('name');
如果 post 陣列中不包含這個值則返回 null。
與 get 方法相同,你也可以給 post 方法第二個參數傳遞一個默認值,如果 post 陣列中沒找到對應值則返回默認值。例如:
$request->post('name', 'tom');
助手函數 input()
與 $request->input()
函數類似,可以獲取到所有參數, input() 助手函數共有兩個參數:
- name: 獲取的參數名稱 (如果為空,可以獲取所有參數的陣列)
- default: 默認值 (通過第一個參數獲取失敗後,會使用該參數的值)
例如
// 獲取參數 name
$name = input('name');
// 獲取參數 name,如果不存在則使用默認值
$name = input('name','張三');
// 獲取全部參數
$all_params = input();
獲得原始請求 post 包體
$post = $request->rawBody();
這個功能類似與 php-fpm
裡的 file_get_contents("php://input");
操作。用於獲得 http 原始請求包體。這在獲取非 application/x-www-form-urlencoded
格式的 post 請求數據時很有用。
獲取 header
獲取整個 header 陣列
$request->header();
如果請求沒有 header 參數則返回一個空的陣列。注意所有 key 均為小寫。
獲取 header 陣列的某一個值
$request->header('host');
如果 header 陣列中不包含這個值則返回 null。注意所有 key 均為小寫。
與 get 方法相同,你也可以給 header 方法第二個參數傳遞一個默認值,如果 header 陣列中沒找到對應值則返回默認值。例如:
$request->header('host', 'localhost');
獲取 cookie
獲取整個 cookie 陣列
$request->cookie();
如果請求沒有 cookie 參數則返回一個空的陣列。
獲取 cookie 陣列的某一個值
$request->cookie('name');
如果 cookie 陣列中不包含這個值則返回 null。
與 get 方法相同,你也可以給 cookie 方法第二個參數傳遞一個默認值,如果 cookie 陣列中沒找到對應值則返回默認值。例如:
$request->cookie('name', 'tom');
獲得所有輸入
包含了 post
get
的集合。
$request->all();
獲取指定輸入值
從 post
get
的集合中獲取某個值。
$request->input('name', $default_value);
獲取部分輸入數據
從 post
get
的集合中獲取部分數據。
// 獲取 username 和 password 組成的陣列,如果對應的 key 沒有則忽略
$only = $request->only(['username', 'password']);
// 獲得除了 avatar 和 age 以外的所有輸入
$except = $request->except(['avatar', 'age']);
通過控制器參數獲得輸入
<?php
namespace app\controller;
use support\Response;
class UserController
{
public function create(string $name, int $age = 18): Response
{
return json(['name' => $name, 'age' => $age]);
}
}
代碼邏輯類似於
<?php
namespace app\controller;
use support\Request;
use support\Response;
class UserController
{
public function create(Request $request): Response
{
$name = $request->input('name');
$age = (int)$request->input('age', 18);
return json(['name' => $name, 'age' => $age]);
}
}
更多信息請參考 控制器參數綁定
獲取上傳文件
提示
上傳文件需要使用multipart/form-data
格式的表單
獲取整個上傳文件陣列
$request->file();
表單類似:
<form method="post" action="http://127.0.0.1:8787/upload/files" enctype="multipart/form-data" />
<input name="file1" multiple="multiple" type="file">
<input name="file2" multiple="multiple" type="file">
<input type="submit">
</form>
$request->file()
返回的格式類似:
array (
'file1' => object(webman\Http\UploadFile),
'file2' => object(webman\Http\UploadFile)
)
它是一個 webman\Http\UploadFile
實例的陣列。webman\Http\UploadFile
類繼承了 PHP 內置的 SplFileInfo
類,並且提供了一些實用的方法。
<?php
namespace app\controller;
use support\Request;
class UploadController
{
public function files(Request $request)
{
foreach ($request->file() as $key => $spl_file) {
var_export($spl_file->isValid()); // 文件是否有效,例如 true|false
var_export($spl_file->getUploadExtension()); // 上傳文件後綴名,例如 'jpg'
var_export($spl_file->getUploadMimeType()); // 上傳文件 mime 類型,例如 'image/jpeg'
var_export($spl_file->getUploadErrorCode()); // 獲取上傳錯誤碼,例如 UPLOAD_ERR_NO_TMP_DIR UPLOAD_ERR_NO_FILE UPLOAD_ERR_CANT_WRITE
var_export($spl_file->getUploadName()); // 上傳文件名,例如 'my-test.jpg'
var_export($spl_file->getSize()); // 獲得文件大小,例如 13364,單位字節
var_export($spl_file->getPath()); // 獲得上傳的目錄,例如 '/tmp'
var_export($spl_file->getRealPath()); // 獲得臨時文件路徑,例如 `/tmp/workerman.upload.SRliMu`
}
return response('ok');
}
}
注意:
- 文件被上傳後會被命名為一個臨時文件,類似
/tmp/workerman.upload.SRliMu
- 上傳文件大小受到 defaultMaxPackageSize 限制,默認 10M,可在
config/server.php
文件中修改max_package_size
更改默認值。 - 請求結束後臨時文件將被自動清除
- 如果請求沒有上傳文件則
$request->file()
返回一個空的陣列 - 上傳的文件不支持
move_uploaded_file()
方法,請使用$file->move()
方法代替,參見下面的例子
獲取特定上傳文件
$request->file('avatar');
如果文件存在的話則返回對應文件的 webman\Http\UploadFile
實例,否則返回 null。
例子
<?php
namespace app\controller;
use support\Request;
class UploadController
{
public function file(Request $request)
{
$file = $request->file('avatar');
if ($file && $file->isValid()) {
$file->move(public_path().'/files/myfile.'.$file->getUploadExtension());
return json(['code' => 0, 'msg' => 'upload success']);
}
return json(['code' => 1, 'msg' => 'file not found']);
}
}
獲取 host
獲取請求的 host 信息。
$request->host();
如果請求的地址是非標準的 80 或者 443 端口,host 信息可能會攜帶端口,例如 example.com:8080
。如果不需要端口第一個參數可以傳入 true
。
$request->host(true);
獲取請求方法
$request->method();
返回值可能是 GET
、POST
、PUT
、DELETE
、OPTIONS
、HEAD
中的其中一個。
獲取請求 uri
$request->uri();
返回請求的 uri,包括 path 和 queryString 部分。
獲取請求路徑
$request->path();
返回請求的 path 部分。
獲取請求 queryString
$request->queryString();
返回請求的 queryString 部分。
獲取請求 url
url()
方法返回不帶有 Query
參數的 URL。
$request->url();
返回類似 //www.workerman.net/workerman-chat
fullUrl()
方法返回帶有 Query
參數的 URL。
$request->fullUrl();
返回類似 //www.workerman.net/workerman-chat?type=download
注意
url()
和fullUrl()
沒有返回協議部分 (沒有返回 http 或者 https)。
因為瀏覽器里使用//example.com
這樣以//
開頭的地址會自動識別當前站點的協議,自動以 http 或 https 發起請求。
如果你使用了 nginx 代理,請將 proxy_set_header X-Forwarded-Proto $scheme;
加入到 nginx 配置中,參考 nginx 代理,
這樣就可以用 $request->header('x-forwarded-proto');
來判斷是 http 還是 https,例如:
echo $request->header('x-forwarded-proto'); // 輸出 http 或 https
獲取請求 HTTP 版本
$request->protocolVersion();
返回字符串 1.1
或者 1.0
。
獲取請求 sessionId
$request->sessionId();
返回字符串,由字母和數字組成
獲取請求客戶端 IP
$request->getRemoteIp();
獲取請求客戶端端口
$request->getRemotePort();
獲取請求客戶端真實 IP
$request->getRealIp($safe_mode=true);
當項目使用代理 (例如 nginx) 時,使用 $request->getRemoteIp()
得到的往往是代理伺服器 IP (類似 127.0.0.1
192.168.x.x
) 並非客戶端真實 IP。這時候可以嘗試使用 $request->getRealIp()
獲得客戶端真實 IP。
$request->getRealIp()
會嘗試從 HTTP 頭的 x-forwarded-for
、x-real-ip
、client-ip
、x-client-ip
、via
字段中獲取真實 IP。
由於 HTTP 頭很容伪造,所以此方法獲得的客戶端 IP 並非 100% 可信,尤其是
$safe_mode
為 false 時。透過代理獲得客戶端真實 IP 的比較可靠的方法是,已知安全的代理伺服器 IP,並且明確知道攜帶真實 IP 是哪個 HTTP 頭,如果$request->getRemoteIp()
返回的 IP 確認為已知的安全的代理伺服器,然後通過$request->header('攜帶真實IP的HTTP頭')
獲取真實 IP。
獲取伺服器 IP
$request->getLocalIp();
獲取伺服器端口
$request->getLocalPort();
判斷是否是 ajax 請求
$request->isAjax();
判斷是否是 pjax 請求
$request->isPjax();
判斷是否是期待 json 返回
$request->expectsJson();
判斷客戶端是否接受 json 返回
$request->acceptJson();
獲得請求的插件名
非插件請求返回空字符串 ''
。
$request->plugin;
獲得請求的應用名
單應用的時候始終返回空字符串 ''
,多應用 的時候返回應用名
$request->app;
因為閉包函數不屬於任何應用,所以來自閉包路由的請求
$request->app
始終返回空字符串''
閉包路由參見 路由
獲得請求的控制器類名
獲得控制器對應的類名
$request->controller;
返回類似 app\controller\IndexController
因為閉包函數不屬於任何控制器,所以來自閉包路由的請求
$request->controller
始終返回空字符串''
閉包路由參見 路由
獲得請求的方法名
獲得請求對應的控制器方法名
$request->action;
返回類似 index
因為閉包函數不屬於任何控制器,所以來自閉包路由的請求
$request->action
始終返回空字符串''
閉包路由參見 路由
重寫參數
有時候我們想重寫請求的參數,例如將請求過濾,然後重新賦值給請求對象,這時候我們可以使用 setGet()
setPost()
setHeader()
方法。
重寫 GET 參數
$request->get(); // 假設得到 ['name' => 'tom', 'age' => 18]
$request->setGet(['name' => 'tom']);
$request->get(); // 最終得到 ['name' => 'tom']
注意
如例子所示,setGet()
是重寫所有 GET 參數,setPost()
setHeader()
也是同樣的行為。
重寫 POST 參數
$post = $request->post();
foreach ($post as $key => $value) {
$post[$key] = htmlspecialchars($value);
}
$request->setPost($post);
$request->post(); // 得到過濾後的 post 參數
重寫 HEADER 參數
$request->setHeader(['host' => 'example.com']);
$request->header('host'); // 輸出 example.com