20、PHP 8.4 新特性 - 新函数 http_(get|clear)_last_response_headers
在 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_headers
和 http_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_headers
和 http_clear_last_response_headers
函数,因为 $http_response_header
变量仅在本地作用域内可用,而 http_(get|clear)_last_response_headers
函数并不返回或清除作用域内的变量。