PHPGraphQLAPI实现与最佳实践
PHP GraphQL API实现与最佳实践
GraphQL是一种API查询语言,让客户端可以精确地获取需要的数据,不多不少。PHP中有多个GraphQL实现库,今天说说如何在PHP中搭建GraphQL服务。
GraphQL的核心概念是Schema、Query和Mutation。Schema定义了可查询的数据类型和操作。
```php
require 'vendor/autoload.php';
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Schema;
use GraphQL\GraphQL;
// 定义类型
$userType = new ObjectType([
'name' => 'User',
'fields' => [
'id' => Type::int(),
'name' => Type::string(),
'email' => Type::string(),
'age' => Type::int(),
'posts' => [
'type' => Type::listOf(fn() => $postType),
'resolve' => function ($user) {
return getPostsByUserId($user['id']);
},
],
],
]);
$postType = new ObjectType([
'name' => 'Post',
'fields' => [
'id' => Type::int(),
'title' => Type::string(),
'content' => Type::string(),
'author_id' => Type::int(),
'created_at' => Type::string(),
'author' => [
'type' => Type::listOf(fn() => $userType),
'resolve' => function ($post) {
return getUsers(['id' => $post['author_id']]);
},
],
],
]);
// 定义查询
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'user' => [
'type' => $userType,
'args' => [
'id' => Type::nonNull(Type::int()),
],
'resolve' => function ($root, $args) {
$users = getUsers(['id' => $args['id']]);
return $users[0] ?? null;
},
],
'users' => [
'type' => Type::listOf($userType),
'resolve' => function () {
return getUsers();
},
],
'post' => [
'type' => $postType,
'args' => [
'id' => Type::nonNull(Type::int()),
],
'resolve' => function ($root, $args) {
$posts = getPosts(['id' => $args['id']]);
return $posts[0] ?? null;
},
],
'posts' => [
'type' => Type::listOf($postType),
'args' => [
'author_id' => Type::int(),
],
'resolve' => function ($root, $args) {
if (isset($args['author_id'])) {
return getPostsByUserId($args['author_id']);
}
return getPosts();
},
],
],
]);
// 定义变更
$mutationType = new ObjectType([
'name' => 'Mutation',
'fields' => [
'createUser' => [
'type' => $userType,
'args' => [
'name' => Type::nonNull(Type::string()),
'email' => Type::nonNull(Type::string()),
'age' => Type::int(),
],
'resolve' => function ($root, $args) {
return createUser($args['name'], $args['email'], $args['age'] ?? null);
},
],
'updateUser' => [
'type' => $userType,
'args' => [
'id' => Type::nonNull(Type::int()),
'name' => Type::string(),
'email' => Type::string(),
'age' => Type::int(),
],
'resolve' => function ($root, $args) {
return updateUser($args['id'], $args);
},
],
'deleteUser' => [
'type' => Type::boolean(),
'args' => [
'id' => Type::nonNull(Type::int()),
],
'resolve' => function ($root, $args) {
return deleteUser($args['id']);
},
],
],
]);
// 模拟数据源
function getUsers(array $filter = []): array
{
$users = [
['id' => 1, 'name' => '张三', 'email' => 'zhangsan@test.com', 'age' => 28],
['id' => 2, 'name' => '李四', 'email' => 'lisi@test.com', 'age' => 35],
['id' => 3, 'name' => '王五', 'email' => 'wangwu@test.com', 'age' => 22],
];
if (isset($filter['id'])) {
return array_filter($users, fn($u) => $u['id'] === $filter['id']);
}
return $users;
}
function getPosts(array $filter = []): array
{
return [
['id' => 1, 'title' => 'PHP入门', 'content' => '内容1', 'author_id' => 1, 'created_at' => '2024-01-01'],
['id' => 2, 'title' => 'GraphQL基础', 'content' => '内容2', 'author_id' => 1, 'created_at' => '2024-01-15'],
['id' => 3, 'title' => '高级PHP', 'content' => '内容3', 'author_id' => 2, 'created_at' => '2024-02-01'],
];
}
function getPostsByUserId(int $userId): array
{
return array_filter(getPosts(), fn($p) => $p['author_id'] === $userId);
}
function createUser(string $name, string $email, ?int $age): array
{
return ['id' => 4, 'name' => $name, 'email' => $email, 'age' => $age ?? 0];
}
function updateUser(int $id, array $data): array
{
$users = getUsers(['id' => $id]);
if (empty($users)) throw new Exception("用户不存在");
return array_merge($users[0], $data);
}
function deleteUser(int $id): bool
{
return true;
}
// 处理GraphQL请求
$schema = new Schema([
'query' => $queryType,
'mutation' => $mutationType,
]);
$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, null, $variables);
$output = $result->toArray();
} catch (Exception $e) {
$output = ['errors' => [['message' => $e->getMessage()]]];
}
header('Content-Type: application/json');
echo json_encode($output);
?>
```
GraphQL的查询示例:
```graphql
// 查询示例
query {
user(id: 1) {
name
email
posts {
title
created_at
}
}
users {
name
age
}
}
// 变更示例
mutation {
createUser(name: "赵六", email: "zhao@test.com", age: 28) {
id
name
email
}
}
```
GraphQL相比REST API有几个优势。客户端精确控制返回字段,一次查询获取多个资源,强类型Schema提供自动文档。但GraphQL也有缺点,查询复杂度控制、缓存策略、文件上传等都比REST复杂。选择GraphQL还是REST取决于项目需求。
