From fd451bfad4dd606ec650d89622c5354c732e1535 Mon Sep 17 00:00:00 2001 From: HH Date: Mon, 12 Jan 2026 12:08:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=9A=E4=B8=AA=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=B9=B6=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common.php | 25 +++++++++--- src/extend/HttpExtend.php | 81 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 95 insertions(+), 11 deletions(-) diff --git a/src/common.php b/src/common.php index 668c29ee..b495bb85 100644 --- a/src/common.php +++ b/src/common.php @@ -14,7 +14,7 @@ // | github 仓库地址 :https://github.com/zoujingli/ThinkLibrary // +---------------------------------------------------------------------- -declare (strict_types=1); +declare(strict_types=1); use think\admin\extend\CodeExtend; use think\admin\extend\HttpExtend; @@ -150,7 +150,8 @@ function sysuri(string $url = '', array $vars = [], $suffix = true, $domain = fa $attr[1] = Str::snake($attr[1]); [$rcf, $tmp] = [Library::$sapp->config->get('route', []), uniqid('think_admin_replace_temp_vars_')]; $map = [Str::lower($rcf['default_app'] ?? ''), Str::snake($rcf['default_controller'] ?? ''), Str::lower($rcf['default_action'] ?? '')]; - for ($idx = count($attr) - 1; $idx >= 0; $idx--) if ($attr[$idx] == ($map[$idx] ?: 'index')) $attr[$idx] = $tmp; else break; + for ($idx = count($attr) - 1; $idx >= 0; $idx--) if ($attr[$idx] == ($map[$idx] ?: 'index')) $attr[$idx] = $tmp; + else break; $url = Library::$sapp->route->buildUrl(join('/', $attr), $vars)->suffix($suffix)->domain($domain)->build(); $ext = is_string($suffix) ? $suffix : ($rcf['url_html_suffix'] ?? 'html'); $new = preg_replace("#/{$tmp}(\.{$ext})?#", '', $old = parse_url($url, PHP_URL_PATH) ?: '', -1, $count); @@ -398,6 +399,17 @@ function http_post(string $url, $data, array $options = []) return HttpExtend::post($url, $data, $options); } } +if (!function_exists('http_multi')) { + /** + * 并发执行多个HTTP请求(类似JavaScript的Promise.all) + * @param array $requests 请求配置数组,每个元素格式: ['method' => 'GET', 'url' => '...', 'options' => [...]] + * @return array 返回结果数组,保持与输入数组相同的顺序,每个元素为对应请求的响应内容或false + */ + function http_multi(array $requests): array + { + return HttpExtend::multiRequest($requests); + } +} if (!function_exists('data_save')) { /** * 数据增量保存 @@ -441,14 +453,15 @@ function trace_file(Exception $exception): bool $file = $path . DIRECTORY_SEPARATOR . date('Ymd_His_') . strtr($name, ['/' => '.', '\\' => '.']); $json = json_encode($exception instanceof \think\admin\Exception ? $exception->getData() : [], 64 | 128 | 256); $class = get_class($exception); - return false !== file_put_contents($file, - "[CODE] {$exception->getCode()}" . PHP_EOL . + return false !== file_put_contents( + $file, + "[CODE] {$exception->getCode()}" . PHP_EOL . "[INFO] {$exception->getMessage()}" . PHP_EOL . ($exception instanceof \think\admin\Exception ? "[DATA] {$json}" . PHP_EOL : '') . "[FILE] {$class} in {$name} line {$exception->getLine()}" . PHP_EOL . "[TIME] " . date('Y-m-d H:i:s') . PHP_EOL . PHP_EOL . '[TRACE]' . PHP_EOL . $exception->getTraceAsString() - ); + ); } } if (!function_exists('format_bytes')) { @@ -487,4 +500,4 @@ function format_datetime($datetime, string $format = 'Y年m月d日 H:i:s'): stri return (string)$datetime; } } -} \ No newline at end of file +} diff --git a/src/extend/HttpExtend.php b/src/extend/HttpExtend.php index 91ed8f2b..a9b2fcb2 100644 --- a/src/extend/HttpExtend.php +++ b/src/extend/HttpExtend.php @@ -14,7 +14,7 @@ // | github 仓库地址 :https://github.com/zoujingli/ThinkLibrary // +---------------------------------------------------------------------- -declare (strict_types=1); +declare(strict_types=1); namespace think\admin\extend; @@ -101,6 +101,80 @@ public static function request(string $method, string $location, array $options } } $curl = curl_init(); + static::configureCurl($curl, $method, $location, $options); + $content = curl_exec($curl); + curl_close($curl); + return $content; + } + + /** + * 并发执行多个HTTP请求(类似JavaScript的Promise.all) + * @param array $requests 请求配置数组,每个元素格式: ['method' => 'GET', 'url' => '...', 'options' => [...]] + * @return array 返回结果数组,保持与输入数组相同的顺序,每个元素为对应请求的响应内容或false + */ + public static function multiRequest(array $requests): array + { + if (empty($requests)) { + return []; + } + + $multiHandle = curl_multi_init(); + $curlHandles = []; + $results = []; + + // 初始化所有curl句柄 + foreach ($requests as $index => $request) { + $method = $request['method'] ?? 'GET'; + $location = $request['url'] ?? ''; + $options = $request['options'] ?? []; + + // GET 参数设置 + if (!empty($options['query'])) { + $location .= strpos($location, '?') !== false ? '&' : '?'; + if (is_array($options['query'])) { + $location .= http_build_query($options['query']); + } elseif (is_string($options['query'])) { + $location .= $options['query']; + } + } + + $curl = curl_init(); + static::configureCurl($curl, $method, $location, $options); + curl_multi_add_handle($multiHandle, $curl); + $curlHandles[$index] = $curl; + $results[$index] = false; + } + + // 执行所有请求 + $running = null; + do { + curl_multi_exec($multiHandle, $running); + curl_multi_select($multiHandle); + } while ($running > 0); + + // 获取所有请求的结果 + foreach ($curlHandles as $index => $curl) { + $results[$index] = curl_multi_getcontent($curl); + curl_multi_remove_handle($multiHandle, $curl); + curl_close($curl); + } + + curl_multi_close($multiHandle); + + // 保持原始顺序返回结果 + return array_values($results); + } + + /** + * 配置CURL句柄 + * @param mixed $curl CURL句柄(PHP 7: resource, PHP 8+: CurlHandle) + * @param string $method 请求方式 + * @param string $location 请求地址 + * @param array $options 请求参数 + * @return void + */ + private static function configureCurl($curl, string $method, string $location, array $options): void + { // Agent 代理设置 curl_setopt($curl, CURLOPT_USERAGENT, $options['agent'] ?? static::getUserAgent()); // Cookie 信息设置 @@ -149,9 +223,6 @@ public static function request(string $method, string $location, array $options curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); - $content = curl_exec($curl); - curl_close($curl); - return $content; } /** @@ -173,4 +244,4 @@ private static function getUserAgent(): string ]; return $agents[array_rand($agents)]; } -} \ No newline at end of file +}