# 请求
# 请求对象
HttpRequest
对象封装了当前 Http 请求的所有相关信息,比如参数,Cookie,Session 等。框架会将请求对象自动注入到控制器对应的每个 public
方法中。
注意
我们约定会将请求对象注入到 Controller 方法的第一个参数中,不支持配置。所以如果是路径参数的话,请放在 HttpRequest
参数后面。
namespace app\controller;
use herosphp\core\HttpRequest;
#[Controller(name: HelloController::class, desc: '系统管理-用户管理')]
class HelloController
{
#[Get(uri: '/', desc: 'Index')]
public function hello(HttpRequest $request): string
{
$default_name = 'herosphp';
// 获取 get 参数,name 参数不存在,则返回默认值 $default
$name = $request->get('name', $default);
// 获取所有的参数
$getParams = $request->get();
// 向浏览器返回字符串
return 'hello ' . $name;
}
// 接收路径参数
#[Get(uri: '/user/{userId}', desc: 'User Profile')]
public function user($userId): string
{
return $userId;
}
}
通过$request
对象我们能获取到请求相关的任何数据。
如果它类中获取当前请求的$request
对象,请使用全局变量 WebApp::$request
即可;
$request = WebApp::$request;
$name = $request->get('name');
# API Method
# GET 请求
# 获取整个 get 数组
$request->get();
如果请求没有 get 参数则返回一个空的数组。
# 获取 get 数组的某一个值
$request->get('name');
如果获取失败,则返回 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');
# 获得原始请求 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->getParameter('name', $default_value);
# 获取上传文件
# 获取整个上传文件数组
$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 (
array (
'name' => '123.jpg',
'tmp_name' => '/tmp/workerman.upload.9hjR4w',
'size' => 1196127,
'error' => 0,
'type' => 'application/octet-stream',
),
array (
'name' => '456.txt',
'tmp_name' => '/tmp/workerman.upload.9sirSws',
'size' => 490,
'error' => 0,
'type' => 'text/plain',
)
)
# 获取特定上传文件
$request->file('avatar');
<?php
declare(strict_types=1);
namespace app\modules\utils\controller;
use app\utils\resp\Result;
use herosphp\annotation\Controller;
use herosphp\annotation\Post;
use herosphp\core\BaseController;
use herosphp\core\HttpRequest;
use herosphp\plugin\storage\core\FileInfo;
use herosphp\plugin\storage\core\Uploader;
use herosphp\plugin\storage\Storage;
#[Controller(name: UploadController::class, desc: '上传类')]
class UploadController extends BaseController
{
protected static Uploader $_uploader;
public function __init()
{
parent::__init();
static::$_uploader = Storage::getUploader();
}
#[Post(uri: '/utils/upload', desc: '文件上传')]
public function doUpload(HttpRequest $request): Result
{
/** @var FileInfo $info*/
$info = static::$_uploader->upload($request->file('src'));
if (!$info) {
return Result::error()->message(static::$_uploader->getError()->getMessage());
}
return Result::ok()->data([
'localName' => $info->localName,
'path' => $info->path,
'url' => $info->url,
]);
}
}
说明
- 文件被上传后会被命名为一个临时文件,类似
/tmp/workerman.upload.SRliMu
- 上传文件大小受到defaultMaxPackageSize (opens new window)限制,默认 10M,可在
config/app.config.php
文件中修改max_package_size
更改默认值。 - 请求结束后临时文件将被自动清除
- 如果请求没有上传文件则
$request->file()
返回一个空的数组 - 上传的文件不支持
move_uploaded_file()
方法,该方法只有在通过 FPM 启动的 php 进程中才有效。
# 获取 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.herosphp.dev/demo
fullUrl()
方法返回带有Query
参数 的 URL。
$request->fullUrl();
返回类似//www.herosphp.dev/demo?name=zhangsan
注意:
url()
和fullUrl()
没有返回协议部分(没有返回 http 或者 https)
# 获取请求 HTTP 版本
$request->protocolVersion();
返回字符串 1.1
或者1.0
。
# 获取请求 sessionId
$request->sessionId();
返回字符串,由字母和数字组成
# 获取请求客户端真实 IP
$request->getRealIp($safe_mode=true);
当项目使用代理(例如 nginx)时,使用$request->getRemoteIp()
得到的往往是代理服务器 IP(类似127.0.0.1
192.168.x.x
)并非客户端真实 IP。这时候可以尝试使用$request->getRealIp()
获得客户端真实 IP。
$request->getRealIp();
原理是:如果发现客户端 IP 是内网 IP,则尝试从Client-Ip
、X-Forwarded-For
、X-Real-Ip
、Client-Ip
、Via
HTTP 头中获取真实 IP。如果$safe_mode
为 false,则不判断客户端 IP 是否为内网 IP(不安全),直接尝试从以上 HTTP 头中读取客户端 IP 数据。如果 HTTP 头没有以上字段,则使用$request->getRemoteIp()
的返回值作为结果返回。
由于 HTTP 头很容伪造,所以此方法获得的客户端 IP 并非 100%可信,尤其是
$safe_mode
为 false 时。透过代理获得客户端真实 IP 的最可靠的方法是,已知安全的代理服务器 IP,并且明确知道携带真实 IP 是哪个 HTTP 头,如果$request->getRemoteIp()
返回的 IP 确认为已知的安全的代理服务器,然后通过$request->header('携带真实IP的HTTP头')
获取真实 IP。
# 判断是否是 ajax 请求
$request->isAjax();
# 判断是否是 pjax 请求
$request->isPjax();
# 判断是否是期待 json 返回
$request->expectsJson();
# 判断客户端是否接受 json 返回
$request->acceptJson();
# 获得请求的控制器类名
获得控制器对应对象
WebApp::$targetController
# 获得请求的方法名
获得请求对应的控制器方法名
WebApp::$targetMethod
响应 →