You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 11:07:13