请求

概述

Flight 将 HTTP 请求封装成一个单一的对象,可以通过以下方式访问:

$request = Flight::request();

理解

HTTP 请求是理解 HTTP 生命周期的核心方面之一。用户在网页浏览器或 HTTP 客户端上执行一个操作,他们会向你的项目发送一系列头部、主体、URL 等。你可以捕获这些头部(浏览器的语言、他们能处理的压缩类型、用户代理等),并捕获发送到你的 Flight 应用程序的主体和 URL。这些请求对于你的应用程序了解下一步该做什么至关重要。

基本用法

PHP 有几个超级全局变量,包括 $_GET$_POST$_REQUEST$_SERVER$_FILES$_COOKIE。Flight 将这些抽象成方便的 Collections。你可以将 querydatacookiesfiles 属性访问为数组或对象。

注意: 强烈不鼓励在你的项目中使用这些超级全局变量,应该通过 request() 对象来引用它们。

注意: $_ENV 没有可用的抽象。

$_GET

你可以通过 query 属性访问 $_GET 数组:

// GET /search?keyword=something
Flight::route('/search', function(){
    $keyword = Flight::request()->query['keyword'];
    // 或
    $keyword = Flight::request()->query->keyword;
    echo "You are searching for: $keyword";
    // 使用 $keyword 查询数据库或其他内容
});

$_POST

你可以通过 data 属性访问 $_POST 数组:

Flight::route('POST /submit', function(){
    $name = Flight::request()->data['name'];
    $email = Flight::request()->data['email'];
    // 或
    $name = Flight::request()->data->name;
    $email = Flight::request()->data->email;
    echo "You submitted: $name, $email";
    // 使用 $name 和 $email 保存到数据库或其他内容
});

你可以通过 cookies 属性访问 $_COOKIE 数组:

Flight::route('GET /login', function(){
    $savedLogin = Flight::request()->cookies['myLoginCookie'];
    // 或
    $savedLogin = Flight::request()->cookies->myLoginCookie;
    // 检查它是否真的保存了,如果是则自动登录
    if($savedLogin) {
        Flight::redirect('/dashboard');
        return;
    }
});

有关设置新 cookie 值的帮助,请参阅 overclokk/cookie

$_SERVER

可以通过 getVar() 方法快捷访问 $_SERVER 数组:


$host = Flight::request()->getVar('HTTP_HOST');

$_FILES

你可以通过 files 属性访问上传的文件:

// 直接访问 $_FILES 属性。以下是推荐的方法
$uploadedFile = Flight::request()->files['myFile']; 
// 或
$uploadedFile = Flight::request()->files->myFile;

有关更多信息,请参阅 Uploaded File Handler

处理文件上传

v3.12.0

你可以使用框架的一些辅助方法来处理文件上传。它基本上归结为从请求中拉取文件数据,并将其移动到新位置。

Flight::route('POST /upload', function(){
    // 如果你有一个输入字段如 <input type="file" name="myFile">
    $uploadedFileData = Flight::request()->getUploadedFiles();
    $uploadedFile = $uploadedFileData['myFile'];
    $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename());
});

如果你有多个文件上传,可以循环遍历它们:

Flight::route('POST /upload', function(){
    // 如果你有一个输入字段如 <input type="file" name="myFiles[]">
    $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles'];
    foreach ($uploadedFiles as $uploadedFile) {
        $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename());
    }
});

安全注意: 始终验证和清理用户输入,特别是处理文件上传时。始终验证你允许上传的扩展类型,但你还应该验证文件的“魔术字节”以确保它是用户声称的文件类型。有 文章 可帮助处理此问题。

请求主体

要获取原始 HTTP 请求主体,例如处理 POST/PUT 请求时,你可以这样做:

Flight::route('POST /users/xml', function(){
    $xmlBody = Flight::request()->getBody();
    // 处理发送的 XML。
});

JSON 主体

如果你收到内容类型为 application/json 的请求,并且示例数据为 {"id": 123},它将从 data 属性可用:

$id = Flight::request()->data->id;

请求头部

你可以使用 getHeader()getHeaders() 方法访问请求头部:


// 也许你需要 Authorization 头部
$host = Flight::request()->getHeader('Authorization');
// 或
$host = Flight::request()->header('Authorization');

// 如果你需要获取所有头部
$headers = Flight::request()->getHeaders();
// 或
$headers = Flight::request()->headers();

请求方法

你可以使用 method 属性或 getMethod() 方法访问请求方法:

$method = Flight::request()->method; // 实际上由 getMethod() 填充
$method = Flight::request()->getMethod();

注意: getMethod() 方法首先从 $_SERVER['REQUEST_METHOD'] 拉取方法,然后如果存在 $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']$_REQUEST['_method'],它可以被覆盖。

请求对象属性

请求对象提供以下属性:

  • body - 原始 HTTP 请求主体
  • url - 被请求的 URL
  • base - URL 的父子目录
  • method - 请求方法 (GET, POST, PUT, DELETE)
  • referrer - 引用 URL
  • ip - 客户端 IP 地址
  • ajax - 请求是否为 AJAX 请求
  • scheme - 服务器协议 (http, https)
  • user_agent - 浏览器信息
  • type - 内容类型
  • length - 内容长度
  • query - 查询字符串参数
  • data - 帖子数据或 JSON 数据
  • cookies - Cookie 数据
  • files - 上传的文件
  • secure - 连接是否安全
  • accept - HTTP 接受参数
  • proxy_ip - 客户端的代理 IP 地址。按顺序扫描 $_SERVER 数组中的 HTTP_CLIENT_IPHTTP_X_FORWARDED_FORHTTP_X_FORWARDEDHTTP_X_CLUSTER_CLIENT_IPHTTP_FORWARDED_FORHTTP_FORWARDED
  • host - 请求主机名
  • servername - 来自 $_SERVER 的 SERVER_NAME

辅助方法

有一些辅助方法可以拼凑 URL 的部分,或处理某些头部。

完整 URL

你可以使用 getFullUrl() 方法访问完整的请求 URL:

$url = Flight::request()->getFullUrl();
// https://example.com/some/path?foo=bar

基础 URL

你可以使用 getBaseUrl() 方法访问基础 URL:

// http://example.com/path/to/something/cool?query=yes+thanks
$url = Flight::request()->getBaseUrl();
// https://example.com
// 注意,没有尾随斜杠。

查询解析

你可以将 URL 传递给 parseQuery() 方法来解析查询字符串为关联数组:

$query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar');
// ['foo' => 'bar']

协商内容接受类型

v3.17.2

你可以使用 negotiateContentType() 方法根据客户端发送的 Accept 头部确定最佳响应内容类型。


// 示例 Accept 头部:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
// 下面定义你支持的内容。
$availableTypes = ['application/json', 'application/xml'];
$typeToServe = Flight::request()->negotiateContentType($availableTypes);
if ($typeToServe === 'application/json') {
    // 服务 JSON 响应
} elseif ($typeToServe === 'application/xml') {
    // 服务 XML 响应
} else {
    // 默认使用其他内容或抛出错误
}

注意: 如果在 Accept 头部中找不到任何可用类型,该方法将返回 null。如果没有定义 Accept 头部,该方法将返回 $availableTypes 数组中的第一个类型。

另请参阅

故障排除

  • 如果你的 Web 服务器位于代理、负载均衡器等后面,request()->iprequest()->proxy_ip 可能不同。

更新日志

  • v3.17.2 - 添加了 negotiateContentType()
  • v3.12.0 - 添加了通过请求对象处理文件上传的能力。
  • v1.0 - 初始发布。