Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions src/common.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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')) {
/**
* 数据增量保存
Expand Down Expand Up @@ -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')) {
Expand Down Expand Up @@ -487,4 +500,4 @@ function format_datetime($datetime, string $format = 'Y年m月d日 H:i:s'): stri
return (string)$datetime;
}
}
}
}
81 changes: 76 additions & 5 deletions src/extend/HttpExtend.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// | github 仓库地址 :https://github.com/zoujingli/ThinkLibrary
// +----------------------------------------------------------------------

declare (strict_types=1);
declare(strict_types=1);

namespace think\admin\extend;

Expand Down Expand Up @@ -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 信息设置
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -173,4 +244,4 @@ private static function getUserAgent(): string
];
return $agents[array_rand($agents)];
}
}
}