本文目录导读:

- 安装依赖
- 基础项目结构
- 定义GraphQL Schema
- 实现Resolver(数据获取逻辑)
- 创建Schema
- 入口文件(API端点)
- 添加Mutation(数据变更)
- 使用示例
- 高级特性
- 测试GraphQL API
- 最佳实践
- 集成到主流框架
在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 } }"}'
最佳实践
- 性能优化:使用DataLoader避免N+1问题
- 安全考虑:实现查询深度限制、速率限制
- 错误处理:统一错误格式,提供清晰错误信息
- 文档生成:使用GraphQL Playground或GraphiQL
- 缓存策略:对频繁查询的结果进行缓存
集成到主流框架
Laravel集成
composer require rebing/graphql-laravel
Symfony集成
composer require overblog/graphql-bundle
这就是PHP项目中使用GraphQL的完整指南,通过这种结构化的方式,你可以构建高性能、易维护的GraphQL API。