PHP用cURL发GraphQL请求最简写法是设置Content-Type为application/json,用json_encode将query和variables数组转为JSON发送;响应需检查errors字段而非仅HTTP状态码。

PHP用cURL发GraphQL查询请求最简写法
GraphQL没有专用PHP扩展,直接用cURL构造HTTP请求是最轻量、兼容性最好的方式。关键不是“怎么调”,而是“怎么避免被响应格式和编码坑住”。
核心要点:
-
Content-Type必须设为application/json,否则服务端可能拒绝或返回HTML错误页 - 请求体必须是合法JSON:查询语句用双引号包裹,变量对象单独传,不能把变量拼进query字符串里
- PHP的
json_encode()默认不转义中文和斜杠,但GraphQL服务通常不介意;若遇解析失败,加JSON_UNESCAPED_UNICODE更稳妥
示例(查用户ID为123的姓名和邮箱):
$url = 'https://api.example.com/graphql';
$query = 'query GetUser($id: ID!) { user(id: $id) { name email } }';
$variables = ['id' => '123'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['query' => $query, 'variables' => $variables], JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
if (isset($result['data']['user'])) {
echo $result['data']['user']['name'];
}
用Guzzle发GraphQL请求时怎么传变量才不出错
Guzzle比原生cURL更易读,但新手常把variables当字符串拼进query字段,导致服务端报"Variable '$id' is not defined"。
立即学习“PHP免费学习笔记(深入)”;
正确做法是把query和variables作为顶层键并列提交:
- 不要写
'query' => "query GetUser(\$id: ID!) { user(id: \$id) { name } }", 'variables' => '{"id": "123"}'(variables是字符串) - 要写
'query' => 'query GetUser($id: ID!) { user(id: $id) { name } }', 'variables' => ['id' => '123'](variables是数组,由Guzzle自动JSON序列化) - 如果变量含嵌套对象或null,确保PHP数组结构与GraphQL期望类型一致,比如
['filter' => ['status' => null]]在某些服务端会触发类型校验失败
简短Guzzle示例:
$client = new \GuzzleHttp\Client();
$response = $client->post('https://api.example.com/graphql', [
'json' => [
'query' => 'query GetPost($slug: String!) { post(slug: $slug) { title body } }',
'variables' => ['slug' => 'hello-world']
]
]);
$data = json_decode($response->getBody(), true);
GraphQL响应里出现errors字段但data为空怎么办
这不是网络错误,而是GraphQL执行层报错——比如字段不存在、权限不足、变量类型不匹配。PHP代码里只检查!empty($result['data'])会漏掉这类问题。
- 务必先检查
isset($result['errors']) && !empty($result['errors']),再决定是否读取data - 常见错误信息如
"Cannot query field 'usre' on type 'Query'"(拼写错误)、"Expected type ID!, found \"abc\""(变量类型不符) - 开发期可临时打印
$result['errors'][0]['message']快速定位,上线后应转成日志,避免暴露服务端细节
用graphql-php做客户端?别这么干
webonyx/graphql-php是服务端实现,不是客户端SDK。有人误以为它能“发请求”,结果卡在GraphQL\Executor\Executor::execute()——这函数只执行本地schema,根本不走HTTP。
真要封装请求逻辑,推荐:
- 手写一个轻量
GraphQLClient类,只做query+variables→ JSON → cURL → 解析三步 - 用现成的
vladimir-yuldashev/laravel-graphql(仅Laravel项目)或php-http/httplug适配器生态 - 避免引入全量GraphQL解析器,除非你同时要动态生成查询语句(极少见)
真正容易被忽略的是错误响应的结构一致性:有些GraphQL服务在出错时仍返回HTTP 200,只靠curl_getinfo($ch, CURLINFO_HTTP_CODE)判断会失效。必须解析JSON后看有没有errors字段。











