graphql-php 入门:如何从 .graphql 文件将解析器函数添加到架构?

Con*_*roß 5 graphql graphql-php

我对 GraphQL 完全陌生,想尝试一下 graphql-php 来构建一个简单的 API 来开始。我目前正在阅读文档并尝试示例,但我一开始就陷入困境。

我希望将我的架构存储在schema.graphql文件中,而不是手动构建它,因此我按照文档了解如何执行此操作,并且它确实有效:

<?php
// graph-ql is installed via composer
require('../vendor/autoload.php');

use GraphQL\Language\Parser;
use GraphQL\Utils\BuildSchema;
use GraphQL\Utils\AST;
use GraphQL\GraphQL;

try {
    $cacheFilename = 'cached_schema.php';
    // caching, as recommended in the docs, is disabled for testing
    // if (!file_exists($cacheFilename)) {
        $document = Parser::parse(file_get_contents('./schema.graphql'));
        file_put_contents($cacheFilename, "<?php\nreturn " . var_export(AST::toArray($document), true) . ';');
    /*} else {
        $document = AST::fromArray(require $cacheFilename); // fromArray() is a lazy operation as well
    }*/

    $typeConfigDecorator = function($typeConfig, $typeDefinitionNode) {
        // In the docs, this function is just empty, but I needed to return the $typeConfig, otherwise I got an error
        return $typeConfig;
    };
    $schema = BuildSchema::build($document, $typeConfigDecorator);

    $context = (object)array();

    // this has been taken from one of the examples provided in the repo
    $rawInput = file_get_contents('php://input');
    $input = json_decode($rawInput, true);
    $query = $input['query'];
    $variableValues = isset($input['variables']) ? $input['variables'] : null;
    $rootValue = ['prefix' => 'You said: '];
    $result = GraphQL::executeQuery($schema, $query, $rootValue, $context, $variableValues);
    $output = $result->toArray();
} catch (\Exception $e) {
    $output = [
        'error' => [
            'message' => $e->getMessage()
        ]
    ];
}
header('Content-Type: application/json; charset=UTF-8');
echo json_encode($output);
Run Code Online (Sandbox Code Playgroud)

这就是我的schema.graphql文件的样子:

schema {
    query: Query    
}

type Query {
    products: [Product!]!
}

type Product {
    id: ID!,
    type: ProductType
}

enum ProductType {
    HDRI,
    SEMISPHERICAL_HDRI,
    SOUND
}
Run Code Online (Sandbox Code Playgroud)

我可以查询它例如

query {
  __schema {types{name}}
}
Run Code Online (Sandbox Code Playgroud)

这将按预期返回元数据。但当然现在我想查询实际的产品数据并从数据库中获取数据,为此我需要定义一个解析器函数。

http://webonyx.github.io/graphql-php/type-system/type-language/上的文档声明:“默认情况下,这样的模式是在没有任何解析器的情况下创建的。我们必须依赖默认字段解析器和根值为了针对这个模式执行查询。” - 但没有这样做的例子。

如何为每个类型/字段添加解析器函数?

Con*_*roß 1

这就是我最终所做的......

$rootResolver = array(
    'emptyCart' => function($root, $args, $context, $info) {
        global $rootResolver;
        initSession();
        $_SESSION['CART']->clear();
        return $rootResolver['getCart']($root, $args, $context, $info);
    },
    'addCartProduct' => function($root, $args, $context, $info) {
        global $rootResolver;

        ...

        return $rootResolver['getCart']($root, $args, $context, $info);
    },
    'removeCartProduct' => function($root, $args, $context, $info) {
        global $rootResolver;

        ...

        return $rootResolver['getCart']($root, $args, $context, $info);
    },
    'getCart' => function($root, $args, $context, $info) {
        initSession();
        return array(
            'count' => $_SESSION['CART']->quantity(),
            'total' => $_SESSION['CART']->total(),
            'products' => $_SESSION['CART']->getProductData()
        );
    },
Run Code Online (Sandbox Code Playgroud)

然后在配置中

$config = ServerConfig::create()
    ->setSchema($schema)
    ->setRootValue($rootResolver)
    ->setContext($context)
    ->setDebug(DEBUG_MODE)
    ->setQueryBatching(true)
;

$server = new StandardServer($config);
Run Code Online (Sandbox Code Playgroud)

对我来说,这感觉相当黑客,我可能应该将解析器外包到单独的文件中,但它有效......仍然感到困惑的是,这个任务没有简单的例子,也许比我的解决方案更好......