20、PHP 8.4 新特性 - 新函数 http_(get|clear)_last_response_headers

作者: 温新

图书: 【PHP 8.4 新特性】

阅读: 181

时间: 2025-01-17 16:46:45

PHP 8.4 中,新增了两个与 HTTP 响应头相关的函数:http_get_last_response_headers()http_clear_last_response_headers(),这两个函数属于 PHP 的 http 扩展。

这两个函数可以帮助开发者获取和清除最近的 HTTP 响应头。它们为调试和处理 HTTP 请求提供了方便,特别是与 HTTP 请求相关的响应头信息的获取和管理。

在 PHP 中,http_get_last_response_headers()http_clear_last_response_headers() 函数用于处理 HTTP 响应头,它们涉及到一个潜在的问题:这些函数的作用域不是局限于当前调用上下文。调用 http_get_last_response_headers() 可能会返回上一次 HTTP 请求的响应头,即使当前并没有直接发起 HTTP 请求。

为了避免这种跨请求(cross-request)的影响,并确保获取到的是当前请求的响应头,建议在每次使用 http_get_last_response_headers() 获取响应头之前,调用 http_clear_last_response_headers() 来清除之前的响应头

PHP 8.4 之前

PHP 提供了一个 HTTP 包装器,可以使用标准的文件系统函数访问远程 HTTP 内容。例如,file_get_contents() 函数可以获取远程 HTTP 资源以及文件系统上的常规文件。

在成功建立远程连接后,HTTP 包装器会填充一个名为 $http_response_header 的本地变量。这个变量是在本地作用域中填充的,而不是一个超级全局变量。

这是一个历史遗留的功能,曾经用于使 HTTP 头信息可用,但这个变量的“魔术”性质可能会让人感到困惑,并且在 IDE 和静态分析工具中需要特别处理。

file_get_contents('https://weixin.com');
var_dump($http_response_header);

输出

Array
(
    [0] => HTTP/1.1 302 Found
    [1] => Location: https://weixin.qq.com/
    [2] => Date: Wed, 27-Nov-2024 11:40:09 GMT
    [3] => Content-Length: 0
    [4] => Connection: close
    [5] => Strict-Transport-Security: max-age=15768000
    [6] => HTTP/1.1 200 OK
    [7] => content-type: text/html;charset=utf-8
    [8] => Date: Wed, 27 Nov 2024 11:40:09 GMT
    [9] => Connection: close
    [10] => Content-Length: 109641
    [11] => Strict-Transport-Security: max-age=31536000
)

PHP 8.4 添加了两个名为 http_get_last_response_headers 和 的新 http_clear_last_response_headers 函数,可用于获取和清除最后一个 HTTP 包装器响应的 HTTP 标头,它可以替换历史的 $http_response_header 变量。

PHP 8.4 中,$http_response_header 变量 并未被弃用,但为了提高代码的可维护性和兼容性,PHP 官方推荐开发者在需要使用 PHP 8.4 或更高版本的应用中,采用新的函数来代替使用这个变量。

http_get_last_response_headers

/**
 * 返回使用 HTTP 包装器的最后一个 HTTP 请求的响应头。
 * 如果请求失败,或者没有最后一个 HTTP 请求,则返回 null。
 *
 * @return array|null
 */
function http_get_last_response_headers(): ?array {}

在使用 HTTP 包装器进行调用并收到成功响应后,http_get_last_response_headers 函数将返回一个包含 HTTP 响应头的数组。如果没有 HTTP 响应,或者请求失败(例如由于 DNS 解析失败),则返回值将为 null

$http_response_header 不同,此函数返回的值不受作用域限制。即使最后一个 HTTP 请求是在另一个函数调用的作用域中进行的,该函数也可以返回其 HTTP 响应头。

请注意,所有 HTTP 响应,包括 404、403 等,也被视为有效的 HTTP 响应,此函数也会返回它们的响应头。

<?php

declare(strict_types=1);

http_get_last_response_headers(); // null

file_get_contents('https://qq.com');
print_r(http_get_last_response_headers());

输出

Array
(
    [0] => HTTP/1.1 302 Moved Temporarily
    [1] => Server: stgw
    [2] => Date: Wed, 27 Nov 2024 11:37:20 GMT
    [3] => Content-Type: text/html
    [4] => Content-Length: 137
    [5] => Connection: close
    [6] => Location: https://www.qq.com/
    [7] => HTTP/1.1 200 OK
    [8] => Date: Wed, 27 Nov 2024 11:37:21 GMT
    [9] => Content-Type: application/json
    [10] => Content-Length: 18
    [11] => Connection: close
    [12] => Server: tRPC-Gateway
    [13] => Inews_trace_id: 40396647091127193721
    [14] => Inews-Trace-Id: 40396647091127193721
    [15] => X-Upstream-Latency: 0
    [16] => X-Proxy-Latency: 0
    [17] => X-Frame-Options: SAMEORIGIN
    [18] => Content-Security-Policy: frame-ancestors none
)

http_get_last_response_headers() 函数即使 $http_response_header 变量被修改过,也会返回响应头(如果有的话)。

$http_response_header 变量在第一次使用 HTTP 包装器之前是未定义的。在这种情况下,http_get_last_response_headers() 函数将返回 null,并且不会发出任何错误、警告或通知。

http_clear_last_response_headers

/**
 * 清除最近一次 HTTP 包装器 HTTP 响应的 HTTP 头。
 */
function http_clear_last_response_headers(): void {}

调用 http_clear_last_response_headers 会清除内部存储的 HTTP 响应头,后续调用 http_get_last_response_headers 将返回 null

调用此函数不会影响 $http_response_header 变量。然而,由于 http_get_last_response_headers 的返回值不受作用域限制,http_clear_last_response_headers() 也会全局清除这些值

替换 $http_response_header 变量

$http_response_header 变量是一个历史遗留的行为,它是在当前作用域内隐式创建的变量。考虑使用 http_get_last_response_headershttp_clear_last_response_headers 函数来替换该变量,因为这些函数提供了更可预测和直观的代码流程。

在 PHP 8.4 中,$http_response_header 变量并没有被弃用。然而,建议尽可能使用新的函数。

跨版本兼容:

 file_get_contents('https://weixin.com');

 $headers = $http_response_header;
 if (\PHP_VERSION_ID >= 80400) {
   $headers = http_get_last_response_headers();
   http_clear_last_response_headers();
 }
 else {
   $headers = $http_response_header;
 }

PHP >=8.4

 file_get_contents('https://qq.com');

 $headers = $http_response_header;
 $headers = http_get_last_response_headers();
 http_clear_last_response_headers();

向后兼容性影响

在旧版本的 PHP 中,无法通过 polyfill(多态填充)来实现 http_get_last_response_headershttp_clear_last_response_headers 函数,因为 $http_response_header 变量仅在本地作用域内可用,而 http_(get|clear)_last_response_headers 函数并不返回或清除作用域内的变量。

请登录后再评论