softonic/graphql-client
Composer 安装命令:
composer require softonic/graphql-client
包简介
Softonic GraphQL client
README 文档
README
PHP Client for GraphQL
Main features
- Client with Oauth2 Support
- Easy query/mutation execution
- Simple array results for mutation and queries
- Powerful object results for mutation and queries
- Filter results
- Manipulate results precisely and bulk
- Transform query results in mutations
Installation
Via composer:
composer require softonic/graphql-client
Documentation
Instantiate a client
You can instantiate a simple client or with Oauth2 support.
Simple Client
<?php $client = \Softonic\GraphQL\ClientBuilder::build('https://your-domain/graphql');
OAuth2 provider
This package allows you to use thephpleague/oauth2-client adapters for authentication, so the endpoint depends on the adapter that you are using. The adapter could be custom or provided by the library as official or third party.
This is an example using a custom provider.
<?php $options = [ 'clientId' => 'myclient', 'clientSecret' => 'mysecret', ]; $provider = new Softonic\OAuth2\Client\Provider\Softonic($options); $config = ['grant_type' => 'client_credentials', 'scope' => 'myscope']; $cache = new \Symfony\Component\Cache\Adapter\FilesystemAdapter(); $client = \Softonic\GraphQL\ClientBuilder::buildWithOAuth2Provider( 'https://your-domain/graphql', $provider, $config, $cache );
Using the GraphQL Client
You can use the client to execute queries and mutations and get the results.
<?php /** * Query Example */ $query = <<<'QUERY' query GetFooBar($idFoo: String, $idBar: String) { foo(id: $idFoo) { id_foo bar (id: $idBar) { id_bar } } } QUERY; $variables = [ 'idFoo' => 'foo', 'idBar' => 'bar', ]; /** @var \Softonic\GraphQL\Client $client */ $response = $client->query($query, $variables); if($response->hasErrors()) { // Returns an array with all the errors found. $response->getErrors(); } else { // Returns an array with all the data returned by the GraphQL server. $response->getData(); } /** * Mutation Example */ $mutation = <<<'MUTATION' mutation ($foo: ObjectInput!){ CreateObjectMutation (object: $foo) { status } } MUTATION; $variables = [ 'foo' => [ 'id_foo' => 'foo', 'bar' => [ 'id_bar' => 'bar' ] ] ]; /** @var \Softonic\GraphQL\Client $client */ $response = $client->query($mutation, $variables); if($response->hasErrors()) { // Returns an array with all the errors found. $response->getErrors(); } else { // Returns an array with all the data returned by the GraphQL server. $response->getData(); }
In the previous examples, the client is used to execute queries and mutations. The response object is used to get the results in array format.
This can be convenient for simple use cases, but it is not recommended for complex results or when you need to use that output to generate mutations. For this reason, the client provides another output called data objects. Those objects allow you to get the results in a more convenient format, allowing you to generate mutations, apply filters, etc.
How to use a data object and transform it to a mutation query
The query result can be obtained as an object which will provide facilities to convert it to a mutation and modify the data easily. At the end, the mutation object will be able to be used as the variables of the mutation query in the GraphQL client.
First we execute a "read" query and obtain the result as an object compound of Items and Collections.
$response = $client->query($query, $variables); $data = $response->getDataObject(); /** * $data = new QueryItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_author' => 1234, * 'genre' => 'adventure', * 'chapters' => new QueryCollection([ * new QueryItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 1, * 'name' => 'Chapter One', * 'pov' => 'first person', * 'pages' => new QueryCollection([]), * ]), * new QueryItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'name' => 'Chapter two', * 'pov' => 'third person', * 'pages' => new QueryCollection([ * new QueryItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'id_page' => 1, * 'has_illustrations' => false, * ]), * new QueryItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'id_page' => 2, * 'has_illustrations' => false, * ]), * ]), * ]), * ]), * ]); */
We can also filter the results in order to work with fewer data later. The filter method returns a new object with the filtered results, so you need to reassign the object to the original one, if you want to modify it.
$data->chapters = $data->chapters->filter(['pov' => 'third person']); /** * $data = new QueryItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_author' => 1234, * 'genre' => 'adventure', * 'chapters' => new QueryCollection([ * new QueryItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'name' => 'Chapter two', * 'pov' => 'third person', * 'pages' => new QueryCollection([ * new QueryItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'id_page' => 1, * 'has_illustrations' => false, * ]), * new QueryItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'id_page' => 2, * 'has_illustrations' => false, * ]), * ]), * ]), * ]), * ]); */
Then we can generate the mutation variables object from the previous query results. This is build using a mutation config. The config for each type has the following parameters:
- linksTo: the location in the query result object where the data can be obtained for that type. If not present, it means it's a level that has no data from the source.
- type: mutation object type (Item or Collection).
- children: if the mutation has a key which value is another mutation type.
$mutationConfig = [ 'book' => [ 'linksTo' => '.', 'type' => MutationItem::class, 'children' => [ 'chapters' => [ 'type' => MutationItem::class, 'children' => [ 'upsert' => [ 'linksTo' => '.chapters', 'type' => MutationCollection::class, 'children' => [ 'pages' => [ 'type' => MutationItem::class, 'children' => [ 'upsert' => [ 'linksTo' => '.chapters.pages', 'type' => MutationCollection::class, ], ], ], ], ], ], ], ], ], ]; $mutation = Mutation::build($mutationConfig, $data); /** * $mutation = new MutationItem([ * 'book' => new MutationItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_author' => 1234, * 'genre' => 'adventure', * 'chapters' => new MutationItem([ * 'upsert' => new MutationCollection([ * new MutationItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 1, * 'name' => 'Chapter One', * 'pov' => 'first person', * 'pages' => new MutationItem([ * 'upsert' => new MutationCollection([]), * ]), * ]), * new MutationItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'name' => 'Chapter two', * 'pov' => 'third person', * 'pages' => new MutationItem([ * 'upsert' => new MutationCollection([ * new MutationItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'id_page' => 1, * 'has_illustrations' => false, * ]), * new MutationItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'id_page' => 2, * 'has_illustrations' => false, * ]), * ]), * ]), * ]), * ]), * ]), * ]), * ]); */
Now we can modify the mutation data using the following methods:
- add(): Adds an Item to a Collection.
- set(): Updates some values of an Item. It also works on Collections, updating all its Items.
- filter(): Filters the Items of a Collection.
- count(): Counts the Items of a Collection.
- isEmpty(): Check if a Collection is empty.
- has(): Checks whether an Item has an argument or not. Works on Collections too. Dot notation is also allowed.
- hasItem(): Checks whether a Collection has an Item with the provided data or not.
- remove(): Removes an Item from a Collection.
- __unset(): Removes a property from an Item or from all the Items of a Collection.
$mutation->book->chapters->upsert->filter(['id_chapter' => 2])->pages->upsert->add([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', 'id_chapter' => 2, 'id_page' => 3, 'has_illustrations' => false, ]); $mutation->book->chapters->upsert->pages->upsert->filter([ 'id_chapter' => 2, 'id_page' => 2, ])->set(['has_illustrations' => true]); $itemToRemove = new MutationItem([ 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', 'id_chapter' => 2, 'id_page' => 1, 'has_illustrations' => false, ]); $mutation->book->chapters->upsert->files->upsert->remove($itemToRemove); unset($mutation->book->chapters->upsert->pov); /** * $mutation = new MutationItem([ * 'book' => new MutationItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_author' => 1234, * 'genre' => 'adventure', * 'chapters' => new MutationItem([ * 'upsert' => new MutationCollection([ * new MutationItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 1, * 'name' => 'Chapter One', * 'pages' => new MutationItem([ * 'upsert' => new MutationCollection([]), * ]), * ]), * new MutationItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'name' => 'Chapter two', * 'pages' => new MutationItem([ * 'upsert' => new MutationCollection([ * new MutationItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'id_page' => 2, * 'has_illustrations' => true, * ]), * new MutationItem([ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'id_page' => 3, * 'has_illustrations' => false, * ]), * ]), * ]), * ]), * ]), * ]), * ]), * ]); */
Finally, the modified mutation data can be passed to the GraphQL client to execute the mutation. When the query is executed, the mutation variables are encoded using json_encode(). This modifies the mutation data just returning the items changed and its parents.
$mutationQuery = <<<'QUERY' mutation ($book: BookInput!){ ReplaceBook (book: $book) { status } } QUERY; $client->mutate($mutationQuery, $mutation);
So the final variables sent to the query would be:
/** * $mutation = [ * 'book' => [ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_author' => 1234, * 'genre' => 'adventure', * 'chapters' => [ * 'upsert' => [ * [ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'name' => 'Chapter two', * 'pages' => [ * 'upsert' => [ * [ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'id_page' => 2, * 'has_illustrations' => true, * ], * [ * 'id_book' => 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d', * 'id_chapter' => 2, * 'id_page' => 3, * 'has_illustrations' => false, * ], * ], * ], * ], * ], * ], * ], * ]; */
NOTE 2: The example has been done for a root Item "book", but it also works for a Collection as root object.
Testing
softonic/graphql-client has a PHPUnit test suite, and a coding style compliance test suite using PHP CS Fixer.
To run the tests, run the following command from the project folder.
$ make tests
To open a terminal in the dev environment:
$ make debug
License
The Apache 2.0 license. Please see LICENSE for more information.
softonic/graphql-client 适用场景与选型建议
softonic/graphql-client 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 3.53M 次下载、GitHub Stars 达 135, 最近一次更新时间为 2017 年 08 月 18 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「client」 「oauth2」 「graphql」 「softonic」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 softonic/graphql-client 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 softonic/graphql-client 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 softonic/graphql-client 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
GraphQL authentication for your headless Craft CMS applications.
A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.
Authorize introspection documentarion for rebing/graphql-laravel
Sylius backend integration for Vue Storefront 2
Mock PSR-18 HTTP client
GraphQL client and query builder.
统计信息
- 总下载量: 3.53M
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 136
- 点击次数: 11
- 依赖项目数: 6
- 推荐数: 0
其他信息
- 授权协议: Apache-2.0
- 更新时间: 2017-08-18