說明

獲得請求物件

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() 助手函數一共有兩個參數:

  1. name: 獲取的參數名稱 (如果為空,可以獲取所有參數的陣列)
  2. 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();

返回值可能是 GETPOSTPUTDELETEOPTIONSHEAD 中的某一個。

獲取請求 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-forx-real-ipclient-ipx-client-ipvia 字段中獲取真實 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