GraphQL服务需手动接管ThinkPHP的POST /graphql请求,用getRawInput()获取原始body并解析,通过contextValue传入Request和Model实例供resolver使用,时间字段须转为DateTime对象以满足ISO 8601格式要求。

GraphQL 服务入口怎么挂到 ThinkPHP 路由上
ThinkPHP 默认不处理 POST /graphql 这类非 RESTful 请求,直接扔给 Webonyx 的 GraphQL\Server\StandardServer 会因请求体解析失败而报错或返回空响应。
必须手动接管原始请求体,并确保 Content-Type 是 application/json 或 application/graphql:
- 在控制器中用
$this->request->getRawInput()拿原始 body(别用input(),它会二次 decode) - 若前端发的是 query 字符串(非 JSON),需手动构造
['query' => $rawInput]再传给执行器 - 路由必须显式允许 POST,且关闭中间件对 JSON 自动解析(比如
json中间件会提前 consume body)
// app/controller/Api.php
public function graphql()
{
$raw = $this->request->getRawInput();
$input = json_decode($raw, true) ?: ['query' => $raw];
$result = \GraphQL\GraphQL::executeQuery(
$this->getSchema(),
$input['query'] ?? '',
new QueryResolver(),
null,
$input['variables'] ?? []
);
return json($result->toArray());
}
Schema 定义里 resolver 怎么访问 ThinkPHP 的 Model 和 Request
Webonyx 的 resolver 是纯函数式调用,不自动注入容器或上下文。硬写 new User() 或直接调用 input() 会导致测试难、耦合重、无法 mock。
推荐把 ThinkPHP 实例通过 contextValue 透传进去:
立即学习“PHP免费学习笔记(深入)”;
- 在
executeQuery()调用时传入['request' => $this->request, 'model' => new UserModel()] - resolver 函数签名必须带第三个参数
$context,从中取所需对象 - 避免在 Schema 定义阶段就 new 实例,否则每次请求都重建,影响性能
$schema = new Schema([
'query' => new ObjectType([
'name' => 'Query',
'fields' => [
'user' => [
'type' => $userType,
'args' => ['id' => Type::int()],
'resolve' => function ($root, $args, $context) {
return $context['model']->find($args['id']);
}
]
]
])
]);
字段类型映射容易踩的坑:ThinkPHP 的时间戳 vs GraphQL 的 DateTime
ThinkPHP 的 datetime 字段默认转成字符串(如 "2024-05-12 14:30:00"),但 GraphQL 的 DateTime 类型要求 ISO 8601 格式("2024-05-12T14:30:00+08:00"),直接返回会触发类型校验失败。
- 不要依赖 Webonyx 的
DateTimeType自动转换 —— 它只认 PHPDateTimeInterface实例 - 在 Model 的
getCreateTimeAttr里统一转成new \DateTime($value) - 如果字段是字符串,resolver 里必须手动 new,不能直接 return 字符串
- 注意时区:ThinkPHP 默认用系统时区,GraphQL 前端可能按 UTC 解析,建议后端统一输出带偏移的 ISO 格式
开发期调试 GraphQL 查询失败,先看这三处日志
Webonyx 报错信息极简,常见 "Cannot query field 'xxx' on type 'Query'" 看似 Schema 问题,实际可能是加载顺序或缓存导致的假象。
- 查
runtime/log/*.log里是否有ParseError或SchemaValidationError—— 表示 Schema 构建失败,但 HTTP 响应仍是 200 + 空数据 - 打开 ThinkPHP 的
app_debug = true,并在executeQuery()外包 try/catch,打印$e->getTraceAsString() - 检查
vendor/webonyx/graphql-php/src/Utils/AST.php是否被 OPcache 缓存 —— 修改 Schema 后清下 OPcache,否则改了也不生效
Schema 是运行时构建的,不是配置文件,任何一处 PHP 语法错误或类名拼错,都会让整个查询静默失败。


















