{"id":31792737,"url":"https://github.com/fnash/graphql-on-rest-bundle","last_synced_at":"2026-04-17T10:07:17.410Z","repository":{"id":62506079,"uuid":"156879554","full_name":"fnash/graphql-on-rest-bundle","owner":"fnash","description":"Build a GraphQL layer on top of a Rest server (API platform + Rest + json-ld)","archived":false,"fork":false,"pushed_at":"2019-07-08T13:52:07.000Z","size":23,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-10T17:16:17.245Z","etag":null,"topics":["api-platform","graphql","json-ld","rest","symfony-bundle"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fnash.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":null,"security":null,"support":null}},"created_at":"2018-11-09T15:18:03.000Z","updated_at":"2019-07-08T13:52:09.000Z","dependencies_parsed_at":"2022-11-02T12:45:40.406Z","dependency_job_id":null,"html_url":"https://github.com/fnash/graphql-on-rest-bundle","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fnash/graphql-on-rest-bundle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnash%2Fgraphql-on-rest-bundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnash%2Fgraphql-on-rest-bundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnash%2Fgraphql-on-rest-bundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnash%2Fgraphql-on-rest-bundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fnash","download_url":"https://codeload.github.com/fnash/graphql-on-rest-bundle/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnash%2Fgraphql-on-rest-bundle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31924404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-17T09:10:15.403Z","status":"ssl_error","status_checked_at":"2026-04-17T09:10:14.455Z","response_time":62,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["api-platform","graphql","json-ld","rest","symfony-bundle"],"created_at":"2025-10-10T17:16:16.563Z","updated_at":"2026-04-17T10:07:17.390Z","avatar_url":"https://github.com/fnash.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GraphqlOnRestBundle\nMain goal: Write a graphQL query, it will navigate your (Rest + JSON-LD) server and do the HTTP calls for you.\n\nThis Symfony bundle lets you build a GraphQL layer to automate HTTP calls to an API Platform based server (JSON-LD + REST).\nIt is built on top of webonyx/graphql-php.\n\nIncludes\n============\n\n- Command to validate graphql schema\n\n```bash\n$ bin/console graphql_on_rest:schema:validate\n```\n\n- Data profiler to dump GraphQL queries et HTTP requests\n\n\nInstallation\n============\n\nDownload the bundle\n----------------\n\n```bash\n    $ composer require fnash/graphql-on-rest-bundle\n```\n\nRegister in the Kernel\n----------------\n\n```php\n\n    \u003c?php\n\n    // app/AppKernel.php\n\n    use Symfony\\Component\\HttpKernel\\Kernel;\n\n    class AppKernel extends Kernel\n    {\n        public function registerBundles()\n        {\n            $bundles = [\n                // ...\n\n                new Fnash\\GraphqlOnRestBundle\\FnashGraphqlOnRestBundle(),\n            ];\n\n            // ...\n        }\n\n        // ...\n    }\n```\n\nUsage\n============  \n  \nCreate a REST data provider\n-------------------------    \n\nAdd a server \"my_rest_api\" and tell the bundle how you make your http requests to fetch JSON-LD data.\nSee Configuration.php\n\n\n```yaml\n    \n    # app/config/config.yml\n    fnash_graphql_on_rest:\n        servers:\n            my_rest_api:\n                data_provider_id: 'Acme\\AppBundle\\GraphQL\\MyDataProvider'\n```            \n            \n```php\n\u003c?php\n\nnamespace Acme\\AppBundle\\GraphQL;\n\nuse Fnash\\GraphqlOnRestBundle\\GraphQL\\DataProvider\\DataProvider;\nuse Symfony\\Component\\Serializer\\Encoder\\DecoderInterface;\n\nclass MyDataProvider extends DataProvider\n{\n    /**\n     * @var DecoderInterface\n     */\n    private $serializer;\n    \n    private $guzzle;\n\n    public function __construct(DecoderInterface $serializer, $guzzle)\n    {\n        $this-\u003eserializer = $serializer;\n        $this-\u003eguzzle = $guzzle;\n    }\n\n    /**\n     * @{inheritdoc}\n     */\n    public function getRawData(string $url, array $queryParams = []): array\n    {\n        try {\n            $data = (string) $this-\u003eguzzle-\u003eget($url, $queryParams)-\u003egetBody();\n\n            return $this-\u003eserializer-\u003edecode($data, 'json');\n        } catch (\\Exception $exception) {\n            return [];\n        }\n        \n        //TODO fill example with symfony/http-client and json_decode (without serializer)\n    }\n    \n    /**\n     * @param string $iri\n     *\n     * @return array\n     */\n    public function getIri(string $iri, $context = null): array\n    {\n        // TODO: Implement getIri() method.\n    }\n\n    /**\n     * @param array $iris\n     *\n     * @return array[]\n     */\n    public function getIris(array $iris, $context = null): array\n    {\n        // TODO: Implement getIris() method.\n    }   \n}\n```\n\nBuild your GraphQL Schema\n----------------------------------\n\nMake sure webonyx/graphql-php is installed\n\n\n1- Define types for your queries:\n\n```php\n\u003c?php\n\nnamespace Acme\\AppBundle\\GraphQL\\Type;\n\nuse Fnash\\GraphqlOnRestBundle\\GraphQL\\Type\\JsonLdObjectType;\nuse Fnash\\GraphqlOnRestBundle\\GraphQL\\Type\\TypeRegistry;\nuse Fnash\\GraphqlOnRestBundle\\GraphQL\\TypeResolver\\TypeResolver;\nuse GraphQL\\Type\\Definition\\Type;\n\nclass ArticleType extends JsonLdObjectType\n{\n    public function __construct($iriResolver)\n    {\n        $config = [\n            'fields' =\u003e function () use ($iriResolver) {\n                $fields = [\n                    'title' =\u003e Type::string(),\n                    'body' =\u003e Type::string(),\n                    'related' =\u003e [\n                        'type' =\u003e Type::listOf(TypeRegistry::get(ArticleType::class)),\n                        'resolve' =\u003e $iriResolver,\n                    ],\n                    'tags' =\u003e [\n                        'type' =\u003e Type::listOf(TypeRegistry::get(TagType::class)),\n                        'resolve' =\u003e $iriResolver,\n                    ],\n                ];\n\n                return array_merge($fields, TypeRegistry::getInterface(ContentInterfaceType::class)-\u003egetFields());\n            },\n            'resolveField' =\u003e TypeResolver::resolveFieldClosure(),\n        ];\n\n        parent::__construct($config);\n    }\n}\n\n\nnamespace Acme\\AppBundle\\GraphQL\\Type;\n\nuse Fnash\\GraphqlOnRestBundle\\GraphQL\\Type\\JsonLdObjectType;\nuse GraphQL\\Type\\Definition\\Type;\n\nclass TagType extends JsonLdObjectType\n{\n    public function __construct()\n    {\n        $config = [\n            'fields' =\u003e function () {\n                $fields = [\n                    'label' =\u003e Type::string(),\n                ];\n\n                return array_merge($fields, static::getMetaDataFields());\n            },\n        ];\n\n        parent::__construct($config);\n    }\n}\n\n```\n\n2- Create resolvers for your types to fetch data:\n\n```php\nnamespace Acme\\AppBundle\\GraphQL\\Resolver;\n\nuse Fnash\\GraphqlOnRestBundle\\GraphQL\\Type\\TypeRegistry;\nuse Fnash\\GraphqlOnRestBundle\\GraphQL\\TypeResolver\\TypeResolver;\nuse Acme\\AppBundle\\GraphQL\\Type\\ArticleType;\nuse GraphQL\\Type\\Definition\\Type;\n\nclass ArticleTypeResolver extends TypeResolver\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function getQueryFieldConfig(): array\n    {\n        $type = $this-\u003egetType();\n\n        $type-\u003eresolveFieldFn = static::resolveFieldClosure();\n\n        $this-\u003econfigureArguments([\n                'id' =\u003e Type::listOf(Type::string()),\n                'title',\n            ]);\n\n        return [\n            'type' =\u003e Type::listOf($type),\n            'resolve' =\u003e $this-\u003eresolveTypeClosure($this-\u003egetUrlPath()),\n            'args' =\u003e $this-\u003egetArgumentsConfig(),\n        ];\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getType(): Type\n    {\n        return TypeRegistry::get(ArticleType::class, [\n            $this-\u003eresolveIriDeferredClosure(),\n        ]);\n    }\n}\n\n\n\u003c?php\n\nnamespace Acme\\AppBundle\\GraphQL\\Resolver;\n\nuse Fnash\\GraphqlOnRestBundle\\GraphQL\\Type\\TypeRegistry;\nuse Fnash\\GraphqlOnRestBundle\\GraphQL\\TypeResolver\\TypeResolver;\nuse Acme\\AppBundle\\GraphQL\\Type\\TagType;\nuse GraphQL\\Type\\Definition\\ResolveInfo;\nuse GraphQL\\Type\\Definition\\Type;\n\nclass TagTypeResolver extends TypeResolver\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function getQueryFieldConfig(): array\n    {\n        $type = $this-\u003egetType();\n\n        $type-\u003eresolveFieldFn = static::resolveFieldClosure();\n\n        return [\n            'type' =\u003e Type::listOf($type),\n            'resolve' =\u003e $this-\u003eresolveTypeClosure($this-\u003egetUrlPath()),\n            'args' =\u003e $this-\u003egetArgumentsConfig(),\n        ];\n    }\n\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getType(): Type\n    {\n        return TypeRegistry::get(TagType::class);\n    }\n}\n\n```\n\n- Resolvers must be declared as services and tagged\n\n```yaml\nservices:\n    Acme\\AppBundle\\GraphQL\\Resolver\\ArticleTypeResolver:\n        parent: 'graphql_on_rest.type_resolver.my_rest_api'\n        tags:\n            - { name: 'graphql_on_rest.type_resolver', server: 'my_rest_api' }\n            \n    Acme\\AppBundle\\GraphQL\\Resolver\\TagTypeResolver:\n        parent: 'graphql_on_rest.type_resolver.my_rest_api'\n        tags:\n            - { name: 'graphql_on_rest.type_resolver', server: 'my_rest_api' }\n```\n\n\nExecute your queries\n----------------------------------   \n  \nQuery 1:\n```graphql\n{\n  article {\n    title\n    body\n  }\n}\n```\n\nResult:\n```graphql\n{\n  \"data\": {\n    \"article\": [\n      {\n        \"title\": \"Nissan rappelle 2 millions de voitures dans le monde\",\n        \"body\": \"\u003cp\u003e\u003cstrong\u003eAFP - \u003c/strong\u003eLe constructeur automobile japonais Nissan a annoncé jeudi\u003cp\u003e\"\n      },\n      {\n        \"title\": \"Vols suspects en série chez les journalistes travaillant sur l'affaire Bettencourt\",\n        \"body\": \"\u003cp\u003eDes enregistrements réalisés chez Liliane Bettencourt...\u003c/p\u003e\"\n      }\n    ]\n  },\n  \"extensions\": {\n    \"http_calls\": [\n      {\n        \"url\": \"/api/articles?limit=2\",\n        \"duration_ms\": 355.484\n      }\n    ],\n    \"query\": {\n      \"duration_ms\": 379,\n      \"duration_no_http_ms\": 6.554\n    }\n  }\n}\n```\n\n\nQuery 2:\n\n```graphql\n{\n  article {\n    title\n    body\n    tags {\n      label\n    }\n  }\n}\n```\n\nResult:\n```graphql\n{\n  \"data\": {\n    \"article\": [\n      {\n        \"title\": \"Nissan rappelle 2 millions de voitures dans le monde\",\n        \"body\": \"\u003cp\u003e\u003cstrong\u003eAFP - \u003c/strong\u003eLe constructeur automobile japonais Nissan a annoncé jeudi\u003cp\u003e\"\n        \"tags\": []\n      },\n      {\n        \"title\": \"Vols suspects en série chez les journalistes travaillant sur l'affaire Bettencourt\",\n                \"body\": \"\u003cp\u003eDes enregistrements réalisés chez Liliane Bettencourt...\u003c/p\u003e\"\n        \"tags\": [\n          {\n            \"label\": \"Justice\"\n          },\n          {\n            \"label\": \"France\"\n          },\n          {\n            \"label\": \"Affaire Bettencourt\"\n          },\n          {\n            \"label\": \"dépêches\"\n          }\n        ]\n      }\n    ]\n  },\n  \"extensions\": {\n    \"http_calls\": [\n      {\n        \"url\": \"/api/articles?limit=2\",\n        \"duration_ms\": 340.168\n      },\n      {\n        \"url\": \"/api/tags?id[0]=8f498ca0-ba33-11e7-add7-02420a050002\u0026id[1]=8f3afcee-ba33-11e7-a697-02420a050002\u0026id[2]=8f1eebee-ba33-11e7-b2fe-02420a050002\u0026id[3]=8a6d60ee-ba33-11e7-9177-02420a050002\u0026limit=4\",\n        \"duration_ms\": 91.786\n      }\n    ],\n    \"query\": {\n      \"duration_ms\": 470,\n      \"duration_no_http_ms\": 18.419\n    }\n  }\n}\n```\n\nTODO\n============\n- update webonyx version","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffnash%2Fgraphql-on-rest-bundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffnash%2Fgraphql-on-rest-bundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffnash%2Fgraphql-on-rest-bundle/lists"}