PHP项目中如何使用GraphQL?

wen PHP项目 7

本文目录导读:

PHP项目中如何使用GraphQL?

  1. 安装依赖
  2. 基础项目结构
  3. 定义GraphQL Schema
  4. 实现Resolver(数据获取逻辑)
  5. 创建Schema
  6. 入口文件(API端点)
  7. 添加Mutation(数据变更)
  8. 使用示例
  9. 高级特性
  10. 测试GraphQL API
  11. 最佳实践
  12. 集成到主流框架

在PHP项目中使用GraphQL,主要推荐使用官方的 webonyx/graphql-php 库,以下是完整的使用指南:

安装依赖

composer require webonyx/graphql-php

基础项目结构

project/
├── src/
│   ├── GraphQL/
│   │   ├── Schema/
│   │   │   └── schema.php
│   │   ├── Types/
│   │   │   ├── QueryType.php
│   │   │   └── UserType.php
│   │   └── Resolvers/
│   │       └── UserResolver.php
│   └── Models/
│       └── User.php
├── public/
│   └── index.php
└── composer.json

定义GraphQL Schema

创建类型(Types)

// src/GraphQL/Types/UserType.php
namespace App\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
class UserType extends ObjectType
{
    public function __construct()
    {
        $config = [
            'name' => 'User',
            'description' => '用户信息',
            'fields' => [
                'id' => Type::int(),
                'name' => Type::string(),
                'email' => Type::string(),
                'age' => Type::int(),
                'createdAt' => Type::string(),
            ],
        ];
        parent::__construct($config);
    }
}

定义查询类型

// src/GraphQL/Types/QueryType.php
namespace App\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use App\GraphQL\Resolvers\UserResolver;
class QueryType extends ObjectType
{
    public function __construct()
    {
        $config = [
            'name' => 'Query',
            'fields' => [
                'user' => [
                    'type' => Type::listOf(new UserType()),
                    'description' => '获取用户列表',
                    'args' => [
                        'id' => Type::int(),
                        'name' => Type::string(),
                    ],
                    'resolve' => function ($root, $args) {
                        $resolver = new UserResolver();
                        return $resolver->getUsers($args);
                    }
                ],
                'userById' => [
                    'type' => new UserType(),
                    'args' => [
                        'id' => Type::nonNull(Type::int()),
                    ],
                    'resolve' => function ($root, $args) {
                        $resolver = new UserResolver();
                        return $resolver->getUserById($args['id']);
                    }
                ],
            ],
        ];
        parent::__construct($config);
    }
}

实现Resolver(数据获取逻辑)

// src/GraphQL/Resolvers/UserResolver.php
namespace App\GraphQL\Resolvers;
use App\Models\User;
class UserResolver
{
    private $userModel;
    public function __construct()
    {
        $this->userModel = new User(); // 假设有User模型
    }
    public function getUsers(array $args): array
    {
        // 查询数据库逻辑
        $query = $this->userModel->newQuery();
        if (isset($args['id'])) {
            $query->where('id', $args['id']);
        }
        if (isset($args['name'])) {
            $query->where('name', 'like', '%' . $args['name'] . '%');
        }
        return $query->get()->toArray();
    }
    public function getUserById(int $id): ?array
    {
        $user = $this->userModel->find($id);
        return $user ? $user->toArray() : null;
    }
}

创建Schema

// src/GraphQL/Schema/schema.php
namespace App\GraphQL\Schema;
use GraphQL\Type\Schema;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use App\GraphQL\Types\QueryType;
class AppSchema
{
    public static function create(): Schema
    {
        return new Schema([
            'query' => new QueryType(),
            // 如果需要mutation,添加:
            // 'mutation' => new MutationType(),
        ]);
    }
}

入口文件(API端点)

// public/index.php
require_once __DIR__ . '/../vendor/autoload.php';
use GraphQL\GraphQL;
use GraphQL\Error\DebugFlag;
use App\GraphQL\Schema\AppSchema;
// 初始化Schema
$schema = AppSchema::create();
// 解析请求
$rawInput = file_get_contents('php://input');
$input = json_decode($rawInput, true);
$query = $input['query'] ?? '';
$variables = $input['variables'] ?? null;
try {
    // 执行查询
    $result = GraphQL::executeQuery(
        $schema,
        $query,
        null, // rootValue
        [], // context
        $variables
    );
    // 返回结果
    $output = $result->toArray(DebugFlag::INCLUDE_DEBUG_MESSAGE);
} catch (\Exception $e) {
    $output = [
        'errors' => [
            [
                'message' => $e->getMessage()
            ]
        ]
    ];
}
header('Content-Type: application/json');
echo json_encode($output);

添加Mutation(数据变更)

// src/GraphQL/Types/MutationType.php
namespace App\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use App\GraphQL\Resolvers\UserResolver;
class MutationType extends ObjectType
{
    public function __construct()
    {
        $config = [
            'name' => 'Mutation',
            'fields' => [
                'createUser' => [
                    'type' => new UserType(),
                    'args' => [
                        'name' => Type::nonNull(Type::string()),
                        'email' => Type::nonNull(Type::string()),
                        'age' => Type::int(),
                    ],
                    'resolve' => function ($root, $args) {
                        $resolver = new UserResolver();
                        return $resolver->createUser($args);
                    }
                ],
                'updateUser' => [
                    'type' => new UserType(),
                    'args' => [
                        'id' => Type::nonNull(Type::int()),
                        'name' => Type::string(),
                        'email' => Type::string(),
                    ],
                    'resolve' => function ($root, $args) {
                        $resolver = new UserResolver();
                        return $resolver->updateUser($args);
                    }
                ],
                'deleteUser' => [
                    'type' => Type::boolean(),
                    'args' => [
                        'id' => Type::nonNull(Type::int()),
                    ],
                    'resolve' => function ($root, $args) {
                        $resolver = new UserResolver();
                        return $resolver->deleteUser($args['id']);
                    }
                ],
            ],
        ];
        parent::__construct($config);
    }
}

使用示例

查询操作

# 获取所有用户
query {
  user {
    id
    name
    email
  }
}
# 按ID查询用户
query {
  userById(id: 1) {
    id
    name
    email
  }
}
# 带参数的查询
query {
  user(name: "张三") {
    id
    name
    email
    age
  }
}

变更操作

# 创建用户
mutation {
  createUser(name: "李四", email: "lisi@example.com", age: 25) {
    id
    name
    email
  }
}
# 更新用户
mutation {
  updateUser(id: 1, name: "王五") {
    id
    name
    email
  }
}
# 删除用户
mutation {
  deleteUser(id: 1)
}

高级特性

使用中间件和认证

// 在入口文件中添加上下文
$context = [
    'user' => authenticateUser(), // 认证逻辑
    'db' => $dbConnection,
];
$result = GraphQL::executeQuery(
    $schema,
    $query,
    null,
    $context,
    $variables
);

添加数据加载器(DataLoader)

composer require beberlei/dataloader
use DataLoader\DataLoader;
class UserResolver
{
    private $dataLoader;
    public function __construct()
    {
        $this->dataLoader = new DataLoader(function ($ids) {
            // 批量查询
            $users = User::whereIn('id', $ids)->get();
            $indexed = $users->keyBy('id');
            return array_map(function ($id) use ($indexed) {
                return $indexed[$id] ?? null;
            }, $ids);
        });
    }
}

使用Apollo Server风格(可选)

composer require steams/graphql-apollo

测试GraphQL API

# 使用curl测试
curl -X POST http://localhost:8000 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-token" \
  -d '{"query": "{ user { id name email } }"}'

最佳实践

  1. 性能优化:使用DataLoader避免N+1问题
  2. 安全考虑:实现查询深度限制、速率限制
  3. 错误处理:统一错误格式,提供清晰错误信息
  4. 文档生成:使用GraphQL Playground或GraphiQL
  5. 缓存策略:对频繁查询的结果进行缓存

集成到主流框架

Laravel集成

composer require rebing/graphql-laravel

Symfony集成

composer require overblog/graphql-bundle

这就是PHP项目中使用GraphQL的完整指南,通过这种结构化的方式,你可以构建高性能、易维护的GraphQL API。

抱歉,评论功能暂时关闭!