PHP curl_multi_close 函数
最后修改日期:2025 年 4 月 11 日
PHP 的 curl_multi_close 函数用于关闭一组 cURL 句柄。它用于在同时执行多个 cURL 请求后清理资源。此函数是 PHP cURL 多接口的一部分。
基本定义
curl_multi_close 函数关闭一个 cURL 多句柄并释放所有关联的资源。它以一个由 curl_multi_init() 创建的 cURL 多句柄作为其唯一参数。
语法:curl_multi_close(CurlMultiHandle $multi_handle): void。调用此函数后,多句柄将无法再使用。务必在使用完毕后关闭多句柄,以防止内存泄漏。
基础多请求
此示例演示了如何进行多个请求并关闭句柄。
basic_multi.php
<?php
declare(strict_types=1);
$urls = [
"https://jsonplaceholder.typicode.com/posts/1",
"https://jsonplaceholder.typicode.com/posts/2",
"https://jsonplaceholder.typicode.com/posts/3"
];
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$handles[] = $ch;
}
do {
$status = curl_multi_exec($mh, $active);
if ($active) {
curl_multi_select($mh);
}
} while ($active && $status == CURLM_OK);
foreach ($handles as $ch) {
echo curl_multi_getcontent($ch) . "\n";
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
此代码同时获取三个帖子。我们创建单独的句柄,将它们添加到多句柄中,然后执行它们。获取内容后,我们会妥善清理所有资源。
多请求中的错误处理
此示例展示了多 cURL 请求的错误处理。
error_handling.php
<?php
declare(strict_types=1);
$urls = [
"https://jsonplaceholder.typicode.com/posts/1",
"https://invalid.url",
"https://jsonplaceholder.typicode.com/posts/3"
];
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_multi_add_handle($mh, $ch);
$handles[$url] = $ch;
}
do {
$status = curl_multi_exec($mh, $active);
if ($active) {
curl_multi_select($mh);
}
} while ($active && $status == CURLM_OK);
foreach ($handles as $url => $ch) {
if (curl_errno($ch)) {
echo "Error for $url: " . curl_error($ch) . "\n";
} else {
echo "Success for $url\n";
}
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
我们故意包含一个无效 URL 来演示错误处理。每个句柄在执行后都会进行错误检查。在处理完所有请求后,多句柄会被妥善关闭。
并行 API 请求
此示例展示了如何并行从多个 API 获取数据。
parallel_apis.php
<?php
declare(strict_types=1);
$apis = [
"users" => "https://jsonplaceholder.typicode.com/users/1",
"posts" => "https://jsonplaceholder.typicode.com/posts/1",
"comments" => "https://jsonplaceholder.typicode.com/comments/1"
];
$mh = curl_multi_init();
$handles = [];
foreach ($apis as $name => $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$handles[$name] = $ch;
}
do {
$status = curl_multi_exec($mh, $active);
if ($active) {
curl_multi_select($mh);
}
} while ($active && $status == CURLM_OK);
$results = [];
foreach ($handles as $name => $ch) {
$results[$name] = json_decode(curl_multi_getcontent($ch), true);
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
print_r($results);
我们同时从三个不同的 API 端点获取数据。结果存储在一个关联数组中,并带有有意义的键。处理完响应后,所有句柄都会被妥善清理。
为多请求设置自定义标头
此示例演示了为多个请求设置自定义标头。
multi_headers.php
<?php
declare(strict_types=1);
$urls = [
"https://api.example.com/resource1",
"https://api.example.com/resource2"
];
$headers = [
'Authorization: Bearer abc123',
'Content-Type: application/json'
];
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_multi_add_handle($mh, $ch);
$handles[] = $ch;
}
do {
$status = curl_multi_exec($mh, $active);
if ($active) {
curl_multi_select($mh);
}
} while ($active && $status == CURLM_OK);
foreach ($handles as $ch) {
echo curl_multi_getcontent($ch) . "\n";
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
我们在多句柄中的所有请求上设置了相同的自定义标头。标头包括授权和内容类型。处理后,我们会妥善清理所有 cURL 资源。
性能比较:顺序 vs 并行
此示例比较了顺序和并行请求的执行。
performance.php
<?php
declare(strict_types=1);
$urls = array_fill(0, 5, "https://jsonplaceholder.typicode.com/posts/1");
// Sequential requests
$start = microtime(true);
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch);
}
$sequential = microtime(true) - $start;
// Parallel requests
$start = microtime(true);
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$handles[] = $ch;
}
do {
$status = curl_multi_exec($mh, $active);
if ($active) {
curl_multi_select($mh);
}
} while ($active && $status == CURLM_OK);
foreach ($handles as $ch) {
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
$parallel = microtime(true) - $start;
echo "Sequential: " . $sequential . " seconds\n";
echo "Parallel: " . $parallel . " seconds\n";
此代码演示了并行请求的性能优势。我们测量了两种方法的执行时间。并行执行完成后,多句柄会被妥善关闭。
最佳实践
- 资源清理: 务必使用 curl_multi_close 关闭多句柄。
- 错误处理: 执行后检查各个句柄的错误。
- 内存管理: 使用完毕后从多句柄中移除句柄。
- 超时: 为各个句柄设置 CURLOPT_TIMEOUT。
- 并发: 限制同时发起的请求数量。
来源
本教程涵盖了 PHP 的 curl_multi_close 函数,并通过实际示例展示了其在并行 HTTP 请求场景中的用法。