如何通过PHP GraphQL获取Cloudflare过去24小时全量请求数据?
解决Cloudflare GraphQL API获取24小时全量HTTP请求数据的分页问题
核心问题分析
你遇到的无限循环,大概率是终止条件判断失误或者分页起始时间更新逻辑错误:比如没有正确比较最后一条数据的时间与结束时间,或是时间格式不统一导致判断失效,也可能是递归时没处理结果为空的情况。
正确的分页实现方案
Cloudflare GraphQL API的分页需要基于时间范围的递进查询,结合limit参数控制单次返回量,同时严格设置终止条件。以下是具体实现步骤:
1. 确定时间范围
先计算好查询的时间边界,统一用Cloudflare要求的ISO 8601 UTC格式(比如2024-05-20T12:00:00Z):
- 起始时间:当前时间减去24小时
- 结束时间:当前时间
2. 用循环替代递归分页(避免PHP栈溢出)
递归在数据量极大时容易触发PHP栈深度限制,用循环更安全。每次请求后更新查询的起始时间,直到返回结果为空或已覆盖全部时间范围。
3. PHP代码示例
<?php use GuzzleHttp\Client; // 可替换为curl实现 function fetchAllCloudflareRequests() { $apiToken = 'YOUR_CLOUDFLARE_API_TOKEN'; $zoneId = 'YOUR_ZONE_ID'; $client = new Client(['base_uri' => 'https://api.cloudflare.com/client/v4/graphql/']); // 计算UTC时间范围 $endTime = new DateTime('now', new DateTimeZone('UTC')); $startTime = (clone $endTime)->sub(new DateInterval('PT24H')); $currentStartTime = $startTime->format(DateTimeInterface::ATOM); $endTimeStr = $endTime->format(DateTimeInterface::ATOM); $allRequests = []; while (true) { // 构建GraphQL查询 $query = <<<GQL query { viewer { zones(filter: {zoneTag: "$zoneId"}) { httpRequests1mGroups( limit: 10000 filter: { datetime_geq: "$currentStartTime" datetime_lt: "$endTimeStr" } orderBy: [datetime_ASC] ) { datetime // 按需添加其他字段:requests, bytes, clientCountryName等 } } } } GQL; // 发送API请求 $response = $client->post('', [ 'headers' => [ 'Authorization' => "Bearer $apiToken", 'Content-Type' => 'application/json', ], 'json' => ['query' => $query], ]); $data = json_decode($response->getBody(), true); $requests = $data['data']['viewer']['zones'][0]['httpRequests1mGroups'] ?? []; // 无数据则终止循环 if (empty($requests)) { break; } // 合并当前页数据 $allRequests = array_merge($allRequests, $requests); // 更新下一次请求的起始时间 $lastDatetime = end($requests)['datetime']; $currentStartTime = $lastDatetime; // 额外终止条件:最后一条数据时间已达结束时间 $lastTimeStamp = strtotime($lastDatetime); $endTimeStamp = strtotime($endTimeStr); if ($lastTimeStamp >= $endTimeStamp) { break; } } return $allRequests; } ?>
避免无限循环的关键细节
- 双重终止条件:同时判断「返回结果为空」和「最后一条数据时间 >= 结束时间」,覆盖所有边界情况
- 时间格式统一:全程用UTC的ISO 8601格式,避免时区或格式差异导致的时间比较错误
- 处理API限制:Cloudflare API有速率限制,建议添加429状态码的重试逻辑(延迟几秒后重试)
- 避免递归栈溢出:循环比递归更适合处理大量分页请求,不会触发PHP的递归深度限制
内容的提问来源于stack exchange,提问作者Sidney Sousa
相关产品推荐
相关产品推荐

