Hyperf方案 GraphQL接入
【代码】Hyperf方案 GraphQL接入。
·
<?php
/**
* 案例052:GraphQL接入
* 说明:用hyperf/graphql实现GraphQL查询,支持类型系统和复杂查询
* 需要安装的包:hyperf/graphql (^3.1),底层用webonyx/graphql-php
*/
declare(strict_types=1);
namespace App\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
use GraphQL\GraphQL;
use GraphQL\Error\DebugFlag;
/**
* 定义User类型
* GraphQL的类型系统是强类型的,每个字段都要定义类型
*/
class UserType extends ObjectType
{
public function __construct()
{
parent::__construct([
'name' => 'User',
'description' => '用户信息',
'fields' => fn() => [ // 用闭包延迟加载,避免循环依赖
'id' => ['type' => Type::int(), 'description' => '用户ID'],
'name' => ['type' => Type::string(), 'description' => '用户名'],
'email' => ['type' => Type::string()],
'age' => ['type' => Type::int()],
// 关联字段:查用户时可以顺带查他的订单(解决REST接口多次请求问题)
'orders' => [
'type' => Type::listOf(TypeRegistry::order()), // User -> [Order]
'resolve' => function ($user) {
// 只有前端查了orders字段才会执行这里,否则不查DB
return \Hyperf\DbConnection\Db::table('orders')
->where('user_id', $user['id'])
->get()
->toArray();
},
],
],
]);
}
}
/**
* 定义Order类型
*/
class OrderType extends ObjectType
{
public function __construct()
{
parent::__construct([
'name' => 'Order',
'fields' => [
'id' => ['type' => Type::int()],
'amount' => ['type' => Type::float()],
'status' => ['type' => Type::string()],
'created_at' => ['type' => Type::string()],
],
]);
}
}
/**
* 类型注册表,避免重复创建类型实例(GraphQL类型必须是单例)
*/
class TypeRegistry
{
private static array $types = [];
public static function user(): UserType
{
return self::$types['User'] ??= new UserType();
}
public static function order(): OrderType
{
return self::$types['Order'] ??= new OrderType();
}
}
/**
* Query根类型(读操作)
*/
class QueryType extends ObjectType
{
public function __construct()
{
parent::__construct([
'name' => 'Query',
'fields' => [
// 查单个用户:query { user(id: 1) { name, email } }
'user' => [
'type' => TypeRegistry::user(),
'args' => ['id' => Type::nonNull(Type::int())], // id是必填参数
'resolve' => function ($root, array $args) {
$user = \Hyperf\DbConnection\Db::table('users')->find($args['id']);
return $user ? (array) $user : null;
},
],
// 用户列表:query { users(limit: 10) { id, name } }
'users' => [
'type' => Type::listOf(TypeRegistry::user()),
'args' => [
'limit' => ['type' => Type::int(), 'defaultValue' => 20],
'keyword' => ['type' => Type::string()],
],
'resolve' => function ($root, array $args) {
$query = \Hyperf\DbConnection\Db::table('users');
if (!empty($args['keyword'])) {
$query->where('name', 'like', '%' . $args['keyword'] . '%');
}
return $query->limit($args['limit'])->get()->toArray();
},
],
],
]);
}
}
/**
* Mutation根类型(写操作)
*/
class MutationType extends ObjectType
{
public function __construct()
{
parent::__construct([
'name' => 'Mutation',
'fields' => [
// 创建用户:mutation { createUser(name: "张三", email: "test@test.com") { id, name } }
'createUser' => [
'type' => TypeRegistry::user(),
'args' => [
'name' => Type::nonNull(Type::string()),
'email' => Type::nonNull(Type::string()),
'age' => Type::int(),
],
'resolve' => function ($root, array $args) {
$id = \Hyperf\DbConnection\Db::table('users')->insertGetId([
'name' => $args['name'],
'email' => $args['email'],
'age' => $args['age'] ?? null,
'created_at' => date('Y-m-d H:i:s'),
]);
return \Hyperf\DbConnection\Db::table('users')->find($id);
},
],
],
]);
}
}
/**
* GraphQL HTTP Controller
* 所有GraphQL请求都走这一个接口 POST /graphql
*/
class GraphQLController
{
public function handle(\Hyperf\HttpServer\Contract\RequestInterface $request): array
{
// 创建Schema,把Query和Mutation注册进去
$schema = new Schema([
'query' => new QueryType(),
'mutation' => new MutationType(),
]);
$body = $request->post();
$query = $body['query'] ?? ''; // GraphQL查询字符串
$variables = $body['variables'] ?? null; // 变量(前端传的参数)
// 执行GraphQL查询
$result = GraphQL::executeQuery($schema, $query, null, null, $variables);
// 开发环境输出详细错误,生产环境不要暴露错误详情
$debug = env('APP_ENV') === 'dev' ? DebugFlag::INCLUDE_DEBUG_MESSAGE : DebugFlag::NONE;
return $result->toArray($debug);
}
}
更多推荐
所有评论(0)