說明
獲取請求對象
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()); // 文件是否有效,例如ture|false
var_export($spl_file->getUploadExtension()); // 上傳文件後綴名,例如'jpg'
var_export($spl_file->getUploadMimeType()); // 上傳文件mine類型,例如 '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