Request 对象详解
Request 对象是 Viswoole 框架对 Swoole HTTP 请求的面向对象封装,提供了丰富的参数获取、请求头操作、文件处理等能力。它实现了 RequestInterface 接口,并支持通过魔术方法访问底层 Swoole 请求对象的属性和方法。
获取 Request 对象
在控制器中注入
php
use Viswoole\HttpServer\Facade\Request;
public static function index(): array
{
// 使用 Facade 静态调用
$method = Request::getMethod();
$ip = Request::ip();
return ['method' => $method, 'ip' => $ip];
}通过方法参数注入
php
use Viswoole\HttpServer\Request;
public static function data(Request $request): array
{
return [
'uri' => (string)$request->getUri(),
'method' => $request->getMethod()
];
}核心方法
获取参数
get() - GET 查询参数
从 URL 查询字符串(?key=value)中获取参数:
php
/**
* 获取单个参数
*
* @param string|null $key 参数名,null 返回全部
* @param mixed $default 默认值
* @return mixed
*/
Request::get(?string $key = null, mixed $default = null): mixed示例:
php
// URL: /search?keyword=php&category=web&page=1
// 获取单个参数
$keyword = Request::get('keyword'); // "php"
$category = Request::get('category'); // "web"
// 带默认值
$page = Request::get('page', 1); // 1
$sort = Request::get('sort', 'created_at'); // "created_at"
// 获取全部 GET 参数
$all = Request::get(); // ['keyword' => 'php', ...]post() - POST 请求体参数
从 POST 请求体中获取参数(支持 JSON 和表单数据):
php
/**
* @param string|null $key 参数名,null 返回全部
* @param mixed $default 默认值
* @return mixed
*/
Request::post(?string $key = null, mixed $default = null): mixed示例:
php
// Content-Type: application/json
// Body: { "name": "张三", "email": "test@example.com" }
$name = Request::post('name'); // "张三"
$email = Request::post('email'); // "test@example.com"
// 获取全部 POST 数据
$data = Request::post(); // ['name' => '张三', ...]注意: 当 Content-Type 为 application/json 时,框架会自动解析 JSON 并填充到 post 数据中。
param() - 智能参数获取
根据当前请求方法自动选择从 GET 或 POST 获取参数:
php
/**
* GET 请求 → 从查询参数获取
* 其他请求 → 从 POST 获取
*
* @param string|null $key 参数名
* @param mixed $default 默认值
* @param array|string|null $filter 额外过滤器
* @return mixed
*/
Request::param(?string $key = null, mixed $default = null, array|string|null $filter = null): mixed示例:
php
// GET /user?id=100 → 从 GET 获取
$id = Request::param('id');
// POST /user (Body: { "id": 100 }) → 从 POST 获取
$id = Request::param('id');params() - 批量参数获取
一次性获取多个参数:
php
/**
* @param array|string|null $rule 取值规则
* - string: 取单个字段
* - [key1, key2]: 取多个字段
* - [key => default]: 取多个并设置默认值
* - null: 取全部参数
* @param bool $isShowNull 是否保留 null 值的字段
* @return array
*/
Request::params(array|string|null $rule = null, bool $isShowNull = true): array示例:
php
// 获取全部参数
$all = Request::params();
// ['keyword' => 'php', 'page' => '1', 'size' => '10']
// 获取指定字段
$data = Request::params(['keyword', 'page', 'size']);
// ['keyword' => 'php', 'page' => '1', 'size' => '10']
// 获取字段并设置默认值
$data = Request::params([
'keyword' => '',
'page' => 1,
'size' => 10,
'sort' => 'created_at'
]);
// ['keyword' => 'php', 'page' => '1', 'size' => '10', 'sort' => 'created_at']
// 保留 null 值(默认行为)
$data = Request::params(null, true); // 保留 null
// 移除 null 值
$data = Request::params(null, false); // 移除 null请求头操作
getHeader() - 获取请求头
php
/**
* @param string|null $key 标头名称(不区分大小写)
* @param mixed $default 默认值
* @return array|string|null key 为 null 时返回数组,否则返回字符串
*/
Request::getHeader(?string $key = null, mixed $default = null): array|string|null示例:
php
// 获取单个标头(返回字符串)
$contentType = Request::getHeader('content-type'); // "application/json"
$authorization = Request::getHeader('Authorization'); // "Bearer xxxxx"
// 获取全部标头(返回关联数组)
$headers = Request::getHeader();
// [
// 'host' => 'localhost:9501',
// 'content-type' => 'application/json',
// 'authorization' => 'Bearer xxxxx'
// ]
// 带默认值
$accept = Request::getHeader('X-Custom', 'default-value');注意: 所有标头键名统一转换为小写。
hasHeader() - 检查标头是否存在
php
if (Request::hasHeader('authorization')) {
// 存在 Authorization 标头
}setHeader() - 设置/修改请求头
php
/**
* @param string $name 标头名称
* @param string $value 标头值
* @return RequestInterface 支持链式调用
*/
Request::setHeader(string $name, string $value): RequestInterface请求信息
基础信息方法
php
// 获取 HTTP 方法(GET、POST、PUT、DELETE 等)
Request::getMethod(): string
// 获取客户端 IP 地址
// 优先读取 X-Real-IP 标头,回退到 remote_addr
Request::ip(): string
// 获取完整 URI 对象
Request::getUri(): Uri
// 获取请求路径(不含查询参数)
// 优先 path_info,回退到 request_uri
Request::target(): string
// 或使用别名
Request::getPath(): string
// 判断是否为 HTTPS 请求
Request::https(): bool
// 获取 HTTP 协议版本(如 "1.1"、"2")
Request::getProtocolVersion(): string使用示例:
php
public static function info(): array
{
return [
'method' => Request::getMethod(), // "POST"
'ip' => Request::ip(), // "192.168.1.100"
'uri' => (string)Request::getUri(), // "http://example.com/api/user?page=1"
'path' => Request::getPath(), // "/api/user"
'is_https' => Request::https(), // true/false
'protocol' => Request::getProtocolVersion() // "1.1"
];
}URI 对象
getUri() 返回的 Uri 对象提供对 URL 各组成部分的访问:
php
$uri = Request::getUri();
$uri->getScheme(); // "http" 或 "https"
$uri->getHost(); // "example.com"
$uri->getPort(); // 8080 或 null
$uri->getPath(); // "/api/user"
$uri->getQuery(); // "page=1&size=10"
$uri->getUserInfo(); // "user:pass" 或 null
$uri->__toString(); // 完整 URI 字符串Cookie 操作
php
/**
* 获取 Cookie 值
*
* @param string|null $key Cookie 名称
* @param mixed $default 默认值
* @return mixed
*/
Request::cookie(?string $key = null, mixed $default = null): mixed示例:
php
// 获取单个 Cookie
$sessionId = Request::cookie('session_id');
$token = Request::cookie('token', ''); // 默认空字符串
// 获取全部 Cookie
$cookies = Request::cookie();
// ['session_id' => 'abc123', 'token' => 'xyz789']Server 信息
php
/**
* 获取 $_SERVER 等价信息
*
* @param string|null $key 键名
* @param mixed $default 默认值
* @return mixed
*/
Request::getServer(?string $key = null, mixed $default = null): mixed常用 Server 字段:
php
// 请求时间戳(浮点数)
$requestTime = Request::getServer('request_time_float');
// 请求 URI(含查询参数)
$requestUri = Request::getServer('request_uri');
// PATH_INFO
$pathInfo = Request::getServer('path_info');
// 远程地址
$remoteAddr = Request::getServer('remote_addr');
// 远程端口
$remotePort = Request::getServer('remote_port');
// 服务器软件
$serverSoftware = Request::getServer('server_software');文件上传
php
/**
* 获取上传文件
*
* @param string|null $key 表单字段名
* @return UploadedFile|UploadedFile[]|array|null
*/
Request::files(?string $key = null): UploadedFile|array|null详细用法参见 文件上传处理
其他实用方法
判断响应类型
php
// 判断客户端是否期望 JSON 响应
if (Request::isJson()) {
return $response->json($data);
}
// 获取客户端期望的资源类型别名
$type = Request::getAcceptType();
// 可能返回: 'json', 'html', 'text', 'xml', 'image', '*'
// 支持的类型常量
Request::ACCEPT_TYPE = [
'html' => 'text/html,application/xhtml+xml,*/*',
'json' => 'application/json,text/x-json,text/json',
'image' => 'image/png,image/jpg,...',
// ...
];获取原始请求数据
php
// 获取原始请求体(等价于 php://input)
$rawContent = Request::getContent();
// 获取完整 HTTP 报文(含 Header 和 Body)
// 注意:HTTP2 模式下不可用
$rawData = Request::getData();操作请求参数
php
/**
* 合并写入请求参数
*
* @param array $params 要添加的参数
* @param string $type 写入目标: 'get'|'post'|'auto'
*/
Request::addParams(array $params, string $type = 'auto'): void示例:
php
// 添加 GET 参数
Request::addParams(['forced_param' => 'value'], 'get');
// 添加 POST 参数
Request::addParams(['extra_field' => 'data'], 'post');
// 根据当前请求方法自动选择
Request::addParams(['timestamp' => time()], 'auto');XSS 过滤机制
默认过滤行为
框架默认对所有字符串类型的输入应用 htmlspecialchars 过滤,防止 XSS 攻击:
php
// 用户输入: <script>alert('xss')</script>
$name = Request::get('name');
// 输出: <script>alert('xss')</script>默认配置:
php
protected array $filter = [
'htmlspecialchars' => [
'flags' => ENT_QUOTES | ENT_SUBSTITUTE
]
];禁用或修改过滤器
方法一:使用 param() 时传入空过滤器
php
// 不应用任何过滤器,获取原始值
$rawContent = Request::param('content', null, []);方法二:自定义全局过滤器(需继承 Request 类)
php
<?php
declare(strict_types=1);
namespace App\Http;
use Viswoole\HttpServer\Request as BaseRequest;
class Request extends BaseRequest
{
/**
* 自定义过滤器配置
*/
protected array $filter = [
// 使用更严格的 HTML 实体编码
'htmlspecialchars' => ['flags' => ENT_QUOTES | ENT_HTML5],
// 额外去除首尾空白
'trim' => null,
];
}然后在配置文件中替换 Request 类的实现。
方法三:在特定场景使用额外过滤器
php
// 仅对该次取值应用 strip_tags
$html = Request::param('html_content', null, ['strip_tags']);
// 组合多个过滤器
$clean = Request::param('input', null, ['trim', 'strip_tags']);访问底层 Swoole 对象
通过 getSwooleRequest() 获取底层对象
Facade 仅代理方法调用,无法直接访问属性。如需访问底层 Swoole 请求对象的属性,请通过 getSwooleRequest() 获取:
php
// 获取底层 Swoole 请求对象
$swooleRequest = Request::getSwooleRequest();
// 访问 Swoole 属性
$fd = $swooleRequest->fd; // 文件描述符
$headerSize = $swooleRequest->headerSize; // 头部大小
$serverPort = $swooleRequest->server_port; // 服务器端口
// 调用 Swoole 方法
$rawContent = $swooleRequest->rawContent(); // 原始请求内容
$isCompleted = $swooleRequest->isCompleted(); // 是否接收完成
// 设置属性
$swooleRequest->get = ['custom' => 'value']; // 修改 GET 数据获取底层对象引用
php
/**
* 获取底层的 Swoole\Http\Request 对象
* @return \Swoole\Http\Request
*/
Request::getSwooleRequest(): \Swoole\Http\Requestphp
$swooleRequest = Request::getSwooleRequest();
// 可直接操作 Swoole 原始对象的所有属性和方法工厂方法
创建新 Request 实例
用于在非 onRequest 回调场景(如异步任务)中创建请求对象:
php
/**
* @param array $options Swoole\Request::create 配置项
* @return RequestInterface
*/
Request::create(array $options = []): RequestInterface示例:
php
// 在异步任务中模拟请求
$request = Request::create([
'parse_cookie' => true,
'parse_body' => true,
'parse_files' => true,
]);
// 手动设置请求数据
$request->get = ['action' => 'task'];
$request->post = ['data' => 'value'];完整使用示例
php
<?php
declare(strict_types=1);
namespace App\Controller;
use Viswoole\HttpServer\Facade\Request;
use Viswoole\Router\Annotation\AutoController;
use Viswoole\Router\Annotation\RouteMapping;
#[AutoController]
class DebugController
{
/**
* 请求调试信息
*
* GET /debug/request-info
*/
public static function requestInfo(): array
{
return [
// === 基本信息 ===
'method' => Request::getMethod(),
'ip' => Request::ip(),
'https' => Request::https(),
'protocol' => Request::getProtocolVersion(),
// === URL 信息 ===
'uri' => (string)Request::getUri(),
'path' => Request::getPath(),
// === 请求头 ===
'content_type' => Request::getHeader('content-type'),
'accept' => Request::getHeader('accept'),
'user_agent' => Request::getHeader('user-agent'),
'authorization' => Request::getHeader('authorization') ? '***隐藏***' : null,
// === 参数 ===
'get_params' => Request::get(),
'post_params' => Request::post(),
'all_params' => Request::params(),
// === Cookie ===
'cookies' => Request::cookie(),
// === 服务端信息 ===
'server' => [
'request_time' => Request::getServer('request_time_float'),
'remote_addr' => Request::getServer('remote_addr'),
'remote_port' => Request::getServer('remote_port'),
],
// === 客户端期望 ===
'expect_json' => Request::isJson(),
'accept_type' => Request::getAcceptType(),
];
}
/**
* API 接口示例
*
* POST /debug/api-test
* Headers:
* X-API-Key: your-api-key
* X-Request-ID: unique-request-id
* Body: { "query": "搜索关键词", "filters": ["type1", "type2"] }
*/
#[RouteMapping(method: 'POST')]
public static function apiTest(): array
{
// 获取自定义请求头
$apiKey = Request::getHeader('X-API-Key');
$requestId = Request::getHeader('X-Request-ID');
// 获取请求体
$query = Request::post('query');
$filters = Request::post('filters', []);
// 使用 params() 批量获取
$params = Request::params(['query', 'filters'], true);
// 处理业务逻辑...
return [
'request_id' => $requestId,
'query' => $query,
'filters' => $filters,
'results' => [],
'count' => 0
];
}
}最佳实践
1. 优先使用自动注入而非手动获取
php
// ✅ 推荐:使用注解自动注入
public static function search(#[InjectGet] string $keyword): array { ... }
// ❌ 避免:手动从 Request 获取(除非需要特殊处理)
public static function search(): array
{
$keyword = Request::get('keyword');
// ...
}2. 对于复杂逻辑,直接使用 Request 对象
当需要条件判断、批量处理或多源数据时:
php
public static function advancedSearch(): array
{
// 根据 Accept 头决定返回格式
if (Request::isJson()) {
$data = $this->searchLogic();
return $response->json($data);
}
// HTML 请求返回视图
$keyword = Request::get('keyword', '');
return $this->render('search', compact('keyword'));
}3. 注意 XSS 过滤的影响
对于富文本、Markdown 等需要保留 HTML 的场景:
php
// ✅ 正确:获取未过滤的内容
$content = Request::param('content', null, []);
// ❌ 错误:会被转义导致格式丢失
$content = Request::post('content');4. 使用 params() 简化多参数获取
php
// ✅ 推荐:一行代码获取多个参数
extract(Request::params([
'page' => 1,
'size' => 20,
'sort' => 'id',
'order' => 'DESC'
]));
// ❌ 冗余:逐个获取
$page = Request::get('page', 1);
$size = Request::get('size', 20);
$sort = Request::get('sort', 'id');
$order = Request::get('order', 'DESC');