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

如何用PHP Curl实现GraphQL请求?解决JSON格式报错问题

PHP Curl调用Cloudflare GraphQL API报错排查与解决

问题场景

用Insomnia测试GraphQL查询完全正常,但改用PHP Curl实现时触发错误,错误信息如下:

failed to recognize JSON request: 'invalid character 'q' looking for beginning of value'

原PHP Curl代码:

$data = array ("query" => "{
    viewer {
         zones(filter: { zoneTag: '" . $zone . "' }) {
            httpRequestsAdaptive(
                filter: {
                    datetime_geq: '2023-05-10T08:00:00Z'
                    datetime_lt: '2023-05-10T08:05:00Z'
                }
                limit: 10000
                orderBy: [
                    datetime_DESC
                ]
            ) {
                device: clientDeviceType
                clientIP: clientIP
            }
            }
        }
    }
");

$data = http_build_query($data);
$headers = [];
$headers[] = 'Content-Type: application/json';
$headers[] = "Authorization: Bearer $token";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.cloudflare.com/client/v4/graphql");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result_plans = curl_exec($ch);
$result_plans = json_decode($result_plans, true);

curl_close($ch);
$response = $result_plans;

错误原因

  1. 请求格式不匹配:设置了Content-Type: application/json请求头,但用http_build_query()生成的是URL编码的表单数据(格式类似query=%7Bviewer...),服务端期望JSON格式,解析时直接报错,错误信息里的'q'就是URL编码后query的首字母。
  2. 查询字符串拼接有风险:原代码直接拼接$zone变量,容易出现语法错误,也存在注入风险。

修正方案

  • 用json_encode()将请求数据转为标准JSON格式,替代http_build_query()
  • 改用HEREDOC语法编写GraphQL查询,避免字符串拼接的语法问题,同时提升代码可读性

修正后的代码

// 用HEREDOC编写查询,避免字符串拼接错误
$query = <<<GRAPHQL
{
    viewer {
         zones(filter: { zoneTag: "$zone" }) {
            httpRequestsAdaptive(
                filter: {
                    datetime_geq: "2023-05-10T08:00:00Z"
                    datetime_lt: "2023-05-10T08:05:00Z"
                }
                limit: 10000
                orderBy: [
                    datetime_DESC
                ]
            ) {
                device: clientDeviceType
                clientIP: clientIP
            }
        }
    }
}
GRAPHQL;

// 构造JSON格式的请求体
$data = json_encode(['query' => $query]);

$headers = [
    'Content-Type: application/json',
    "Authorization: Bearer $token"
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.cloudflare.com/client/v4/graphql");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

// 可选:生产环境建议保留SSL验证
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

$result_plans = curl_exec($ch);
if (curl_errno($ch)) {
    // 捕获Curl请求错误
    $error_msg = curl_error($ch);
    die("Curl请求错误: $error_msg");
}
$result_plans = json_decode($result_plans, true);

curl_close($ch);
$response = $result_plans;

额外优化建议

如果查询包含动态参数(比如$zone、时间范围),建议用GraphQL变量传递,进一步避免语法错误和注入风险:

$query = <<<GRAPHQL
query GetZoneRequests(\$zoneTag: String!, \$startTime: DateTime!, \$endTime: DateTime!) {
    viewer {
         zones(filter: { zoneTag: \$zoneTag }) {
            httpRequestsAdaptive(
                filter: {
                    datetime_geq: \$startTime
                    datetime_lt: \$endTime
                }
                limit: 10000
                orderBy: [datetime_DESC]
            ) {
                device: clientDeviceType
                clientIP: clientIP
            }
        }
    }
}
GRAPHQL;

$data = json_encode([
    'query' => $query,
    'variables' => [
        'zoneTag' => $zone,
        'startTime' => '2023-05-10T08:00:00Z',
        'endTime' => '2023-05-10T08:05:00Z'
    ]
]);

内容的提问来源于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.22 00:05:32