{"id":23380689,"url":"https://github.com/softonic/graphql-client","last_synced_at":"2025-10-06T13:43:03.759Z","repository":{"id":44840021,"uuid":"100599557","full_name":"softonic/graphql-client","owner":"softonic","description":"PHP Client for GraphQL","archived":false,"fork":false,"pushed_at":"2025-03-26T14:38:12.000Z","size":56,"stargazers_count":132,"open_issues_count":0,"forks_count":25,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-05-29T12:22:30.088Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/softonic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-08-17T12:10:12.000Z","updated_at":"2025-05-26T02:14:27.000Z","dependencies_parsed_at":"2024-03-01T09:44:58.396Z","dependency_job_id":"c6da00aa-e369-47a3-93cc-4a19c0d773e5","html_url":"https://github.com/softonic/graphql-client","commit_stats":{"total_commits":21,"total_committers":9,"mean_commits":"2.3333333333333335","dds":0.6666666666666667,"last_synced_commit":"462cfc5e301a417da3abbf237f6dee2e6d73b99e"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/softonic/graphql-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softonic%2Fgraphql-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softonic%2Fgraphql-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softonic%2Fgraphql-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softonic%2Fgraphql-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/softonic","download_url":"https://codeload.github.com/softonic/graphql-client/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softonic%2Fgraphql-client/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278621847,"owners_count":26017253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-21T20:18:02.230Z","updated_at":"2025-10-06T13:43:03.741Z","avatar_url":"https://github.com/softonic.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PHP GraphQL Client\n\n[![Latest Version](https://img.shields.io/github/release/softonic/graphql-client.svg?style=flat-square)](https://github.com/softonic/graphql-client/releases)\n[![Software License](https://img.shields.io/badge/license-Apache%202.0-blue.svg?style=flat-square)](LICENSE.md)\n[![Build Status](https://github.com/softonic/graphql-client/actions/workflows/build.yml/badge.svg)](https://github.com/softonic/graphql-client/actions/workflows/build.yml)\n[![Total Downloads](https://img.shields.io/packagist/dt/softonic/graphql-client.svg?style=flat-square)](https://packagist.org/packages/softonic/graphql-client)\n[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/softonic/graphql-client.svg?style=flat-square)](http://isitmaintained.com/project/softonic/graphql-client \"Average time to resolve an issue\")\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/softonic/graphql-client.svg?style=flat-square)](http://isitmaintained.com/project/softonic/graphql-client \"Percentage of issues still open\")\n\nPHP Client for [GraphQL](http://graphql.org/)\n\n## Main features\n\n* Client with Oauth2 Support\n* Easy query/mutation execution\n* Simple array results for mutation and queries\n* Powerful object results for mutation and queries\n  * Filter results\n  * Manipulate results precisely and bulk\n  * Transform query results in mutations\n\n## Installation\n\nVia composer:\n```\ncomposer require softonic/graphql-client\n```\n\n## Documentation\n\n### Instantiate a client\n\nYou can instantiate a simple client or with Oauth2 support.\n\n#### Simple Client\n```php\n\u003c?php\n$client = \\Softonic\\GraphQL\\ClientBuilder::build('https://your-domain/graphql');\n```\n\n#### OAuth2 provider\n\nThis package allows you to use [thephpleague/oauth2-client](https://github.com/thephpleague/oauth2-client) adapters for authentication, so the endpoint depends on the adapter that you are using. \nThe adapter could be [custom](https://oauth2-client.thephpleague.com/providers/implementing/) or provided by the library as [official](https://oauth2-client.thephpleague.com/providers/league/) or [third party](https://oauth2-client.thephpleague.com/providers/thirdparty/).\n\nThis is an example using a custom provider.\n\n```php\n\u003c?php\n\n$options = [\n    'clientId'     =\u003e 'myclient',\n    'clientSecret' =\u003e 'mysecret',\n];\n\n$provider = new Softonic\\OAuth2\\Client\\Provider\\Softonic($options);\n\n$config = ['grant_type' =\u003e 'client_credentials', 'scope' =\u003e 'myscope'];\n\n$cache = new \\Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter();\n\n$client = \\Softonic\\GraphQL\\ClientBuilder::buildWithOAuth2Provider(\n    'https://your-domain/graphql',\n    $provider,\n    $config,\n    $cache\n);\n```\n\n### Using the GraphQL Client\n\nYou can use the client to execute queries and mutations and get the results.\n\n```php\n\u003c?php\n\n/**\n * Query Example\n */\n$query = \u003c\u003c\u003c'QUERY'\nquery GetFooBar($idFoo: String, $idBar: String) {\n  foo(id: $idFoo) {\n    id_foo\n    bar (id: $idBar) {\n      id_bar\n    }\n  }\n}\nQUERY;\n\n$variables = [\n    'idFoo' =\u003e 'foo',\n    'idBar' =\u003e 'bar',\n];\n\n/** @var \\Softonic\\GraphQL\\Client $client */\n$response = $client-\u003equery($query, $variables);\n\nif($response-\u003ehasErrors()) {\n    // Returns an array with all the errors found.\n    $response-\u003egetErrors();\n}\nelse {\n    // Returns an array with all the data returned by the GraphQL server.\n    $response-\u003egetData();\n}\n\n/**\n * Mutation Example\n */\n$mutation = \u003c\u003c\u003c'MUTATION'\nmutation ($foo: ObjectInput!){\n  CreateObjectMutation (object: $foo) {\n    status\n  }\n}\nMUTATION;\n$variables = [\n    'foo' =\u003e [\n        'id_foo' =\u003e 'foo', \n        'bar' =\u003e [\n            'id_bar' =\u003e 'bar'\n        ]\n    ]\n];\n\n/** @var \\Softonic\\GraphQL\\Client $client */\n$response = $client-\u003equery($mutation, $variables);\n\nif($response-\u003ehasErrors()) {\n    // Returns an array with all the errors found.\n    $response-\u003egetErrors();\n}\nelse {\n    // Returns an array with all the data returned by the GraphQL server.\n    $response-\u003egetData();\n}\n\n```\n\nIn the previous examples, the client is used to execute queries and mutations. The response object is used to\nget the results in array format.\n\nThis can be convenient for simple use cases, but it is not recommended for complex\nresults or when you need to use that output to generate mutations. For this reason, the client provides another output\ncalled data objects. Those objects allow you to get the results in a more convenient format, allowing you to generate\nmutations, apply filters, etc.\n\n### How to use a data object and transform it to a mutation query\n\nThe query result can be obtained as an object which will provide facilities to convert it to a mutation and modify the data easily.\nAt the end, the mutation object will be able to be used as the variables of the mutation query in the GraphQL client.\n\nFirst we execute a \"read\" query and obtain the result as an object compound of Items and Collections.\n\n``` php\n$response = $client-\u003equery($query, $variables);\n\n$data = $response-\u003egetDataObject();\n\n/**\n * $data = new QueryItem([\n *      'id_book'   =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *      'id_author' =\u003e 1234,\n *      'genre'     =\u003e 'adventure',\n *      'chapters'  =\u003e new QueryCollection([\n *          new QueryItem([\n *              'id_book'    =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *              'id_chapter' =\u003e 1,\n *              'name'       =\u003e 'Chapter One',\n *              'pov'        =\u003e 'first person',\n *              'pages'      =\u003e new QueryCollection([]),\n *          ]),\n *          new QueryItem([\n *              'id_book'    =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *              'id_chapter' =\u003e 2,\n *              'name'       =\u003e 'Chapter two',\n *              'pov'        =\u003e 'third person',\n *              'pages'      =\u003e new QueryCollection([\n *                  new QueryItem([\n *                      'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                      'id_chapter'        =\u003e 2,\n *                      'id_page'           =\u003e 1,\n *                      'has_illustrations' =\u003e false,\n *                  ]),\n *                  new QueryItem([\n *                      'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                      'id_chapter'        =\u003e 2,\n *                      'id_page'           =\u003e 2,\n *                      'has_illustrations' =\u003e false,\n *                  ]),\n *              ]),\n *          ]),\n *      ]),\n *  ]);\n */\n```\n\nWe can also filter the results in order to work with fewer data later. The filter method returns a new object with\nthe filtered results, so you need to reassign the object to the original one, if you want to modify it.\n\n``` php\n$data-\u003echapters = $data-\u003echapters-\u003efilter(['pov' =\u003e 'third person']);\n\n/**\n * $data = new QueryItem([\n *      'id_book'   =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *      'id_author' =\u003e 1234,\n *      'genre'     =\u003e 'adventure',\n *      'chapters'  =\u003e new QueryCollection([\n *          new QueryItem([\n *              'id_book'    =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *              'id_chapter' =\u003e 2,\n *              'name'       =\u003e 'Chapter two',\n *              'pov'        =\u003e 'third person',\n *              'pages'      =\u003e new QueryCollection([\n *                  new QueryItem([\n *                      'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                      'id_chapter'        =\u003e 2,\n *                      'id_page'           =\u003e 1,\n *                      'has_illustrations' =\u003e false,\n *                  ]),\n *                  new QueryItem([\n *                      'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                      'id_chapter'        =\u003e 2,\n *                      'id_page'           =\u003e 2,\n *                      'has_illustrations' =\u003e false,\n *                  ]),\n *              ]),\n *          ]),\n *      ]),\n *  ]);\n */\n```\n\nThen we can generate the mutation variables object from the previous query results. This is build using a mutation config.\nThe config for each type has the following parameters:\n* 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.\n* type: mutation object type (Item or Collection).\n* children: if the mutation has a key which value is another mutation type.\n\n``` php\n$mutationConfig = [\n    'book' =\u003e [\n        'linksTo'  =\u003e '.',\n        'type'     =\u003e MutationItem::class,\n        'children' =\u003e [\n            'chapters'  =\u003e [\n                'type'     =\u003e MutationItem::class,\n                'children' =\u003e [\n                    'upsert' =\u003e [\n                        'linksTo'  =\u003e '.chapters',\n                        'type'     =\u003e MutationCollection::class,\n                        'children' =\u003e [\n                            'pages' =\u003e [\n                                'type'     =\u003e MutationItem::class,\n                                'children' =\u003e [\n                                    'upsert' =\u003e [\n                                        'linksTo'  =\u003e '.chapters.pages',\n                                        'type'     =\u003e MutationCollection::class,\n                                    ],\n                                ],\n                            ],\n                        ],\n                    ],\n                ],\n            ],\n        ],\n    ],   \n];\n\n$mutation = Mutation::build($mutationConfig, $data);\n\n/**\n * $mutation = new MutationItem([\n *     'book' =\u003e new MutationItem([\n *          'id_book'   =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *          'id_author' =\u003e 1234,\n *          'genre'     =\u003e 'adventure',\n *          'chapters'  =\u003e new MutationItem([\n *              'upsert' =\u003e new MutationCollection([\n *                  new MutationItem([\n *                      'id_book'    =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                      'id_chapter' =\u003e 1,\n *                      'name'       =\u003e 'Chapter One',\n *                      'pov'        =\u003e 'first person',\n *                      'pages'      =\u003e new MutationItem([\n *                          'upsert' =\u003e new MutationCollection([]),\n *                      ]),\n *                  ]),\n *                  new MutationItem([\n *                      'id_book'    =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                      'id_chapter' =\u003e 2,\n *                      'name'       =\u003e 'Chapter two',\n *                      'pov'        =\u003e 'third person',\n *                      'pages'      =\u003e new MutationItem([\n *                         'upsert' =\u003e new MutationCollection([\n *                              new MutationItem([\n *                                  'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                                  'id_chapter'        =\u003e 2,\n *                                  'id_page'           =\u003e 1,\n *                                  'has_illustrations' =\u003e false,\n *                              ]),\n *                              new MutationItem([\n *                                  'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                                  'id_chapter'        =\u003e 2,\n *                                  'id_page'           =\u003e 2,\n *                                  'has_illustrations' =\u003e false,\n *                              ]),\n *                          ]),\n *                      ]),\n *                  ]),\n *              ]),\n *          ]),\n *      ]),\n *  ]);\n */\n```\n\n#### Now we can modify the mutation data using the following methods:\n* add(): Adds an Item to a Collection.\n* set(): Updates some values of an Item. It also works on Collections, updating all its Items.\n* filter(): Filters the Items of a Collection.\n* count(): Counts the Items of a Collection.\n* isEmpty(): Check if a Collection is empty.\n* has(): Checks whether an Item has an argument or not. Works on Collections too. Dot notation is also allowed.\n* hasItem(): Checks whether a Collection has an Item with the provided data or not.\n* remove(): Removes an Item from a Collection.\n* __unset(): Removes a property from an Item or from all the Items of a Collection.\n\n``` php\n$mutation-\u003ebook-\u003echapters-\u003eupsert-\u003efilter(['id_chapter' =\u003e 2])-\u003epages-\u003eupsert-\u003eadd([\n    'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n    'id_chapter'        =\u003e 2,\n    'id_page'           =\u003e 3,\n    'has_illustrations' =\u003e false,\n]);\n\n$mutation-\u003ebook-\u003echapters-\u003eupsert-\u003epages-\u003eupsert-\u003efilter([\n    'id_chapter' =\u003e 2,\n    'id_page'    =\u003e 2,\n])-\u003eset(['has_illustrations' =\u003e true]);\n\n$itemToRemove = new MutationItem([\n    'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n    'id_chapter'        =\u003e 2,\n    'id_page'           =\u003e 1,\n    'has_illustrations' =\u003e false,\n]);\n$mutation-\u003ebook-\u003echapters-\u003eupsert-\u003efiles-\u003eupsert-\u003eremove($itemToRemove);\n\nunset($mutation-\u003ebook-\u003echapters-\u003eupsert-\u003epov);\n\n/**\n * $mutation = new MutationItem([\n *     'book' =\u003e new MutationItem([\n *         'id_book'   =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *         'id_author' =\u003e 1234,\n *         'genre'     =\u003e 'adventure',\n *         'chapters'  =\u003e new MutationItem([\n *             'upsert' =\u003e new MutationCollection([\n *                 new MutationItem([\n *                     'id_book'    =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                     'id_chapter' =\u003e 1,\n *                     'name'       =\u003e 'Chapter One',\n *                      'pages'      =\u003e new MutationItem([\n *                          'upsert' =\u003e new MutationCollection([]),\n *                      ]),\n *                 ]),\n *                 new MutationItem([\n *                     'id_book'    =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                     'id_chapter' =\u003e 2,\n *                     'name'       =\u003e 'Chapter two',\n *                     'pages'      =\u003e new MutationItem([\n *                         'upsert' =\u003e new MutationCollection([\n *                             new MutationItem([\n *                                 'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                                 'id_chapter'        =\u003e 2,\n *                                 'id_page'           =\u003e 2,\n *                                 'has_illustrations' =\u003e true,\n *                             ]),\n *                             new MutationItem([\n *                                 'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                                 'id_chapter'        =\u003e 2,\n *                                 'id_page'           =\u003e 3,\n *                                 'has_illustrations' =\u003e false,\n *                             ]),\n *                         ]),\n *                     ]),\n *                 ]),\n *             ]),\n *         ]),\n *     ]),\n * ]);\n */\n```\n\nFinally, the modified mutation data can be passed to the GraphQL client to execute the mutation.\nWhen the query is executed, the mutation variables are encoded using json_encode().\nThis modifies the mutation data just returning the items changed and its parents.\n\n``` php\n$mutationQuery = \u003c\u003c\u003c'QUERY'\nmutation ($book: BookInput!){\n  ReplaceBook (book: $book) {\n    status\n  }\n}\nQUERY;\n\n$client-\u003emutate($mutationQuery, $mutation);\n```\n\nSo the final variables sent to the query would be:\n\n``` php\n/**\n * $mutation = [\n *     'book' =\u003e [\n *         'id_book'   =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *         'id_author' =\u003e 1234,\n *         'genre'     =\u003e 'adventure',\n *         'chapters'  =\u003e [\n *             'upsert' =\u003e [\n *                 [\n *                     'id_book'    =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                     'id_chapter' =\u003e 2,\n *                     'name'       =\u003e 'Chapter two',\n *                     'pages'      =\u003e [\n *                         'upsert' =\u003e [\n *                             [\n *                                 'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                                 'id_chapter'        =\u003e 2,\n *                                 'id_page'           =\u003e 2,\n *                                 'has_illustrations' =\u003e true,\n *                             ],\n *                             [\n *                                 'id_book'           =\u003e 'f7cfd732-e3d8-3642-a919-ace8c38c2c6d',\n *                                 'id_chapter'        =\u003e 2,\n *                                 'id_page'           =\u003e 3,\n *                                 'has_illustrations' =\u003e false,\n *                             ],\n *                         ],\n *                     ],\n *                 ],\n *             ],\n *         ],\n *     ],\n * ];\n */\n```\n\nNOTE 2: The example has been done for a root Item \"book\", but it also works for a Collection as root object.\n\n## Testing\n\n`softonic/graphql-client` has a [PHPUnit](https://phpunit.de) test suite, and a coding style compliance test suite using [PHP CS Fixer](http://cs.sensiolabs.org/).\n\nTo run the tests, run the following command from the project folder.\n\n``` bash\n$ make tests\n```\n\nTo open a terminal in the dev environment:\n``` bash\n$ make debug\n```\n\n## License\n\nThe Apache 2.0 license. Please see [LICENSE](LICENSE) for more information.\n\n[PSR-2]: http://www.php-fig.org/psr/psr-2/\n[PSR-4]: http://www.php-fig.org/psr/psr-4/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftonic%2Fgraphql-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoftonic%2Fgraphql-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftonic%2Fgraphql-client/lists"}