fnash / graphql-on-rest-bundle
为API Platform服务器(REST + JSON-LD)构建GraphQL层
dev-master
2019-07-08 13:51 UTC
Requires
- php: >=7
- symfony/config: ^3.0
- symfony/console: ^3.0
- symfony/dependency-injection: ^3.0
- symfony/framework-bundle: ^3.0
- symfony/http-foundation: ^3.0
- symfony/http-kernel: ^3.0
- symfony/stopwatch: ^3.0
- webonyx/graphql-php: ^v0.11
This package is auto-updated.
Last update: 2024-09-09 01:48:55 UTC
README
主要目标:编写一个GraphQL查询,它将遍历你的(REST + JSON-LD)服务器,并为你执行HTTP调用。
这个Symfony扩展包让你构建一个GraphQL层,以自动化对基于API Platform的服务器(JSON-LD + REST)的HTTP调用。它是基于webonyx/graphql-php构建的。
包含
- 用于验证GraphQL模式的命令
$ bin/console graphql_on_rest:schema:validate
- 数据分析器,用于转储GraphQL查询和HTTP请求
安装
下载扩展包
$ composer require fnash/graphql-on-rest-bundle
在Kernel中注册
<?php // app/AppKernel.php use Symfony\Component\HttpKernel\Kernel; class AppKernel extends Kernel { public function registerBundles() { $bundles = [ // ... new Fnash\GraphqlOnRestBundle\FnashGraphqlOnRestBundle(), ]; // ... } // ... }
用法
创建REST数据提供者
添加服务器"my_rest_api"并告诉扩展包如何进行HTTP请求以获取JSON-LD数据。请参阅Configuration.php
# app/config/config.yml fnash_graphql_on_rest: servers: my_rest_api: data_provider_id: 'Acme\AppBundle\GraphQL\MyDataProvider'
<?php namespace Acme\AppBundle\GraphQL; use Fnash\GraphqlOnRestBundle\GraphQL\DataProvider\DataProvider; use Symfony\Component\Serializer\Encoder\DecoderInterface; class MyDataProvider extends DataProvider { /** * @var DecoderInterface */ private $serializer; private $guzzle; public function __construct(DecoderInterface $serializer, $guzzle) { $this->serializer = $serializer; $this->guzzle = $guzzle; } /** * @{inheritdoc} */ public function getRawData(string $url, array $queryParams = []): array { try { $data = (string) $this->guzzle->get($url, $queryParams)->getBody(); return $this->serializer->decode($data, 'json'); } catch (\Exception $exception) { return []; } //TODO fill example with symfony/http-client and json_decode (without serializer) } /** * @param string $iri * * @return array */ public function getIri(string $iri, $context = null): array { // TODO: Implement getIri() method. } /** * @param array $iris * * @return array[] */ public function getIris(array $iris, $context = null): array { // TODO: Implement getIris() method. } }
构建你的GraphQL模式
确保已安装webonyx/graphql-php
1- 定义查询的类型
<?php namespace Acme\AppBundle\GraphQL\Type; use Fnash\GraphqlOnRestBundle\GraphQL\Type\JsonLdObjectType; use Fnash\GraphqlOnRestBundle\GraphQL\Type\TypeRegistry; use Fnash\GraphqlOnRestBundle\GraphQL\TypeResolver\TypeResolver; use GraphQL\Type\Definition\Type; class ArticleType extends JsonLdObjectType { public function __construct($iriResolver) { $config = [ 'fields' => function () use ($iriResolver) { $fields = [ 'title' => Type::string(), 'body' => Type::string(), 'related' => [ 'type' => Type::listOf(TypeRegistry::get(ArticleType::class)), 'resolve' => $iriResolver, ], 'tags' => [ 'type' => Type::listOf(TypeRegistry::get(TagType::class)), 'resolve' => $iriResolver, ], ]; return array_merge($fields, TypeRegistry::getInterface(ContentInterfaceType::class)->getFields()); }, 'resolveField' => TypeResolver::resolveFieldClosure(), ]; parent::__construct($config); } } namespace Acme\AppBundle\GraphQL\Type; use Fnash\GraphqlOnRestBundle\GraphQL\Type\JsonLdObjectType; use GraphQL\Type\Definition\Type; class TagType extends JsonLdObjectType { public function __construct() { $config = [ 'fields' => function () { $fields = [ 'label' => Type::string(), ]; return array_merge($fields, static::getMetaDataFields()); }, ]; parent::__construct($config); } }
2- 创建用于获取数据的类型的解析器
namespace Acme\AppBundle\GraphQL\Resolver; use Fnash\GraphqlOnRestBundle\GraphQL\Type\TypeRegistry; use Fnash\GraphqlOnRestBundle\GraphQL\TypeResolver\TypeResolver; use Acme\AppBundle\GraphQL\Type\ArticleType; use GraphQL\Type\Definition\Type; class ArticleTypeResolver extends TypeResolver { /** * {@inheritdoc} */ public function getQueryFieldConfig(): array { $type = $this->getType(); $type->resolveFieldFn = static::resolveFieldClosure(); $this->configureArguments([ 'id' => Type::listOf(Type::string()), 'title', ]); return [ 'type' => Type::listOf($type), 'resolve' => $this->resolveTypeClosure($this->getUrlPath()), 'args' => $this->getArgumentsConfig(), ]; } /** * {@inheritdoc} */ public function getType(): Type { return TypeRegistry::get(ArticleType::class, [ $this->resolveIriDeferredClosure(), ]); } } <?php namespace Acme\AppBundle\GraphQL\Resolver; use Fnash\GraphqlOnRestBundle\GraphQL\Type\TypeRegistry; use Fnash\GraphqlOnRestBundle\GraphQL\TypeResolver\TypeResolver; use Acme\AppBundle\GraphQL\Type\TagType; use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; class TagTypeResolver extends TypeResolver { /** * {@inheritdoc} */ public function getQueryFieldConfig(): array { $type = $this->getType(); $type->resolveFieldFn = static::resolveFieldClosure(); return [ 'type' => Type::listOf($type), 'resolve' => $this->resolveTypeClosure($this->getUrlPath()), 'args' => $this->getArgumentsConfig(), ]; } /** * {@inheritdoc} */ public function getType(): Type { return TypeRegistry::get(TagType::class); } }
- 解析器必须声明为服务并标记
services: Acme\AppBundle\GraphQL\Resolver\ArticleTypeResolver: parent: 'graphql_on_rest.type_resolver.my_rest_api' tags: - { name: 'graphql_on_rest.type_resolver', server: 'my_rest_api' } Acme\AppBundle\GraphQL\Resolver\TagTypeResolver: parent: 'graphql_on_rest.type_resolver.my_rest_api' tags: - { name: 'graphql_on_rest.type_resolver', server: 'my_rest_api' }
执行你的查询
查询1
{ article { title body } }
结果
{ "data": { "article": [ { "title": "Nissan rappelle 2 millions de voitures dans le monde", "body": "<p><strong>AFP - </strong>Le constructeur automobile japonais Nissan a annoncé jeudi<p>" }, { "title": "Vols suspects en série chez les journalistes travaillant sur l'affaire Bettencourt", "body": "<p>Des enregistrements réalisés chez Liliane Bettencourt...</p>" } ] }, "extensions": { "http_calls": [ { "url": "/api/articles?limit=2", "duration_ms": 355.484 } ], "query": { "duration_ms": 379, "duration_no_http_ms": 6.554 } } }
查询2
{ article { title body tags { label } } }
结果
{ "data": { "article": [ { "title": "Nissan rappelle 2 millions de voitures dans le monde", "body": "<p><strong>AFP - </strong>Le constructeur automobile japonais Nissan a annoncé jeudi<p>" "tags": [] }, { "title": "Vols suspects en série chez les journalistes travaillant sur l'affaire Bettencourt", "body": "<p>Des enregistrements réalisés chez Liliane Bettencourt...</p>" "tags": [ { "label": "Justice" }, { "label": "France" }, { "label": "Affaire Bettencourt" }, { "label": "dépêches" } ] } ] }, "extensions": { "http_calls": [ { "url": "/api/articles?limit=2", "duration_ms": 340.168 }, { "url": "/api/tags?id[0]=8f498ca0-ba33-11e7-add7-02420a050002&id[1]=8f3afcee-ba33-11e7-a697-02420a050002&id[2]=8f1eebee-ba33-11e7-b2fe-02420a050002&id[3]=8a6d60ee-ba33-11e7-9177-02420a050002&limit=4", "duration_ms": 91.786 } ], "query": { "duration_ms": 470, "duration_no_http_ms": 18.419 } } }
待办事项
- 更新webonyx版本