# 请求

# 请求对象

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');
$request->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();

返回值可能是GETPOSTPUTDELETEOPTIONSHEAD中的一个。

# 获取请求 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-IpX-Forwarded-ForX-Real-IpClient-IpVia 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
上次更新: 10/27/2022, 11:18:25 AM