PHP 怎么提供GraphQL接口

wen PHP项目 3

本文目录导读:

PHP 怎么提供GraphQL接口

  1. 使用 Webonyx GraphQL(最流行)
  2. 使用 Laravel + Lighthouse
  3. 完整示例:PHP 原生实现
  4. 使用框架集成
  5. 关键注意事项

在 PHP 中提供 GraphQL 接口,主要有以下几种方式:

使用 Webonyx GraphQL(最流行)

安装

composer require webonyx/graphql-php

基础实现示例

<?php
require_once 'vendor/autoload.php';
use GraphQL\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
// 1. 定义类型
$queryType = new ObjectType([
    'name' => 'Query',
    'fields' => [
        'hello' => [
            'type' => Type::string(),
            'resolve' => function() {
                return 'Hello World!';
            }
        ],
        'user' => [
            'type' => $userType,
            'args' => [
                'id' => Type::nonNull(Type::int())
            ],
            'resolve' => function($root, $args) {
                return getUserById($args['id']);
            }
        ]
    ]
]);
$userType = new ObjectType([
    'name' => 'User',
    'fields' => [
        'id' => Type::nonNull(Type::int()),
        'name' => Type::string(),
        'email' => Type::string()
    ]
]);
// 2. 创建 Schema
$schema = new Schema([
    'query' => $queryType,
    'mutation' => $mutationType // 可选
]);
// 3. 处理请求
$rawInput = file_get_contents('php://input');
$input = json_decode($rawInput, true);
$query = $input['query'];
$variables = isset($input['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);

使用 Laravel + Lighthouse

安装

composer require nuwave/lighthouse
php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider"

定义 Schema (graphql/schema.graphql)

type Query {
    users: [User!]!
    user(id: ID! @eq): User @find
}
type Mutation {
    createUser(name: String!, email: String!): User! @create
    updateUser(id: ID!, name: String): User! @update
}
type User {
    id: ID!
    name: String!
    email: String!
    posts: [Post!]! @hasMany
}

配置路由

// routes/api.php
Route::middleware('api')->group(function () {
    Route::post('/graphql', function () {
        return app('graphql')->executeQuery();
    });
});

完整示例:PHP 原生实现

创建入口文件 graphql.php

<?php
header('Content-Type: application/json');
require_once 'vendor/autoload.php';
use GraphQL\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
// 模拟数据层
class Database {
    private static $users = [
        1 => ['id' => 1, 'name' => 'Alice', 'email' => 'alice@example.com'],
        2 => ['id' => 2, 'name' => 'Bob', 'email' => 'bob@example.com'],
    ];
    private static $posts = [
        1 => ['id' => 1, 'title' => 'Post 1', 'userId' => 1],
        2 => ['id' => 2, 'title' => 'Post 2', 'userId' => 1],
        3 => ['id' => 3, 'title' => 'Post 3', 'userId' => 2],
    ];
    public static function getUser($id) {
        return isset(self::$users[$id]) ? self::$users[$id] : null;
    }
    public static function getPosts($userId) {
        return array_values(array_filter(self::$posts, function($post) use ($userId) {
            return $post['userId'] == $userId;
        }));
    }
}
// 定义类型
$postType = new ObjectType([
    'name' => 'Post',
    'fields' => [
        'id' => Type::nonNull(Type::int()),
        'title' => Type::string(),
    ]
]);
$userType = new ObjectType([
    'name' => 'User',
    'fields' => [
        'id' => Type::nonNull(Type::int()),
        'name' => Type::string(),
        'email' => Type::string(),
        'posts' => [
            'type' => Type::listOf($postType),
            'resolve' => function($user) {
                return Database::getPosts($user['id']);
            }
        ]
    ]
]);
// 查询类型
$queryType = new ObjectType([
    'name' => 'Query',
    'fields' => [
        'user' => [
            'type' => $userType,
            'args' => [
                'id' => Type::nonNull(Type::int())
            ],
            'resolve' => function($root, $args) {
                return Database::getUser($args['id']);
            }
        ],
        'hello' => [
            'type' => Type::string(),
            'resolve' => function() {
                return 'Hello GraphQL!';
            }
        ]
    ]
]);
// 创建 Schema
$schema = new Schema([
    'query' => $queryType
]);
// 处理请求
try {
    $rawInput = file_get_contents('php://input');
    $input = json_decode($rawInput, true);
    if (!$input || !isset($input['query'])) {
        throw new Exception('Invalid GraphQL query');
    }
    $query = $input['query'];
    $variables = isset($input['variables']) ? $input['variables'] : null;
    $result = GraphQL::executeQuery(
        $schema,
        $query,
        null,
        null,
        $variables
    );
    $output = $result->toArray();
} catch (\Exception $e) {
    $output = [
        'errors' => [
            ['message' => $e->getMessage()]
        ]
    ];
}
echo json_encode($output);

测试请求

curl -X POST http://your-server/graphql.php \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query { user(id: 1) { name email posts { title } } }"
  }'

使用框架集成

Laravel + GraphQL PHP

// routes/api.php
Route::post('/graphql', function (\Illuminate\Http\Request $request) {
    $schema = require app_path('graphql/schema.php');
    $query = $request->input('query');
    $variables = $request->input('variables', []);
    $result = GraphQL::executeQuery($schema, $query, null, [], $variables);
    return response()->json($result->toArray());
});

Symfony + OverblogGraphQLBundle

# config/packages/overblog_graphql.yaml
overblog_graphql:
    definitions:
        schema:
            query: Query
            mutation: Mutation
        mappings:
            types:
                - types: [src/GraphQL/Type]

关键注意事项

  1. Schema 定义:明确定义类型、查询和变更
  2. Resolver 逻辑:每个 field 都有对应的解析函数
  3. 错误处理:适当处理和返回错误信息
  4. 性能优化:考虑 N+1 查询问题,使用 DataLoader
  5. 安全:做查询深度限制、查询复杂度分析
// 安全配置示例
$config = [
    'query_complexity' => 100,
    'query_depth' => 10,
    'max_query_queries' => 100,
];
$result = GraphQL::executeQuery(
    $schema,
    $query,
    null,
    null,
    $variables,
    null,
    null,
    ['query_complexity' => 100]
);

选择哪种方式取决于你的项目需求:

  • 小型项目/学习:直接使用 webonyx/graphql-php
  • Laravel 项目:使用 Lighthouse
  • Symfony 项目:使用 OverblogGraphQLBundle
  • 快速原型:可以考虑 GraphQLite

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