{"id":13499286,"url":"https://github.com/ivome/graphql-relay-php","last_synced_at":"2025-05-16T13:06:55.626Z","repository":{"id":52584808,"uuid":"52395800","full_name":"ivome/graphql-relay-php","owner":"ivome","description":"A library to help construct a graphql-php server supporting react-relay.","archived":false,"fork":false,"pushed_at":"2023-10-20T15:44:09.000Z","size":78,"stargazers_count":271,"open_issues_count":2,"forks_count":27,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-05-02T18:11:39.398Z","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":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ivome.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":"2016-02-23T22:20:17.000Z","updated_at":"2025-03-30T20:06:58.000Z","dependencies_parsed_at":"2024-01-09T13:10:37.526Z","dependency_job_id":"0fac55bf-cef2-4ff4-b703-13312f04f82c","html_url":"https://github.com/ivome/graphql-relay-php","commit_stats":{"total_commits":44,"total_committers":7,"mean_commits":6.285714285714286,"dds":"0.40909090909090906","last_synced_commit":"7055fd45b7e552cee4d1290849b84294b0049373"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivome%2Fgraphql-relay-php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivome%2Fgraphql-relay-php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivome%2Fgraphql-relay-php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivome%2Fgraphql-relay-php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivome","download_url":"https://codeload.github.com/ivome/graphql-relay-php/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253065386,"owners_count":21848246,"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","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-07-31T22:00:31.852Z","updated_at":"2025-05-16T13:06:55.595Z","avatar_url":"https://github.com/ivome.png","language":"PHP","readme":"# Relay Library for graphql-php\n\nThis is a library to allow the easy creation of Relay-compliant servers using\nthe [graphql-php](https://github.com/webonyx/graphql-php) reference implementation\nof a GraphQL server.\n\n[![Build Status](https://travis-ci.org/ivome/graphql-relay-php.svg?branch=master)](https://travis-ci.org/ivome/graphql-relay-php)\n[![Coverage Status](https://coveralls.io/repos/github/ivome/graphql-relay-php/badge.svg?branch=master)](https://coveralls.io/github/ivome/graphql-relay-php?branch=master)\n\n*Note: The code is a port of the original [graphql-relay js implementation](https://github.com/graphql/graphql-relay-js)\nfrom Facebook* (With some minor PHP related adjustments and extensions)\n\n## Current Status: \n\nThe basic functionality with the helper functions is in place along with the tests. Only the asynchronous functionality\nwas not yet ported due to the limitations of PHP. \nSee also discussions [here](https://github.com/ivome/graphql-relay-php/issues/1) and [here](https://github.com/webonyx/graphql-php/issues/42)\n\n## Getting Started\n\nA basic understanding of GraphQL and of the graphql-php implementation is needed\nto provide context for this library.\n\nAn overview of GraphQL in general is available in the\n[README](https://github.com/facebook/graphql/blob/master/README.md) for the\n[Specification for GraphQL](https://github.com/facebook/graphql).\n\nThis library is designed to work with the \n[graphql-php](https://github.com/webonyx/graphql-php) reference implementation\nof a GraphQL server.\n\nAn overview of the functionality that a Relay-compliant GraphQL server should\nprovide is in the [GraphQL Relay Specification](https://facebook.github.io/relay/docs/graphql-relay-specification.html)\non the [Relay website](https://facebook.github.io/relay/). That overview\ndescribes a simple set of examples that exist as [tests](tests) in this\nrepository. A good way to get started with this repository is to walk through\nthat documentation and the corresponding tests in this library together.\n\n## Using Relay Library for graphql-php\n\nInstall this repository via composer: \n\n```sh\ncomposer require ivome/graphql-relay-php\n```\n\nWhen building a schema for [graphql-php](https://github.com/webonyx/graphql-php),\nthe provided library functions can be used to simplify the creation of Relay\npatterns.\n\n### Connections \n\nHelper functions are provided for both building the GraphQL types\nfor connections and for implementing the `resolve` method for fields\nreturning those types.\n\n - `Relay::connectionArgs` returns the arguments that fields should provide when they\nreturn a connection type that supports bidirectional pagination.\n - `Relay::forwardConnectionArgs` returns the arguments that fields should provide\nwhen they return a connection type that only supports forward pagination.\n - `Relay::backwardConnectionArgs` returns the arguments that fields should provide\nwhen they return a connection type that only supports backward pagination.\n - `Relay::connectionDefinitions` returns a `connectionType` and its associated\n`edgeType`, given a node type.\n - `Relay::edgeType` returns a new `edgeType`\n - `Relay::connectionType` returns a new `connectionType`\n - `Relay::connectionFromArray` is a helper method that takes an array and the\narguments from `connectionArgs`, does pagination and filtering, and returns\nan object in the shape expected by a `connectionType`'s `resolve` function.\n - `Relay::cursorForObjectInConnection` is a helper method that takes an array and a\nmember object, and returns a cursor for use in the mutation payload.\n\nAn example usage of these methods from the [test schema](tests/StarWarsSchema.php):\n\n```php\n$shipConnection = Relay::connectionDefinitions([\n    'nodeType' =\u003e $shipType\n]);\n\n// this could also be written as\n//\n// $shipEdge = Relay::edgeType([\n//     'nodeType' =\u003e $shipType\n// ]);\n// $shipConnection = Relay::connectionType([\n//     'nodeType' =\u003e $shipType,\n//     'edgeType' =\u003e $shipEdge\n// ]);\n\n$factionType = new ObjectType([\n    'name' =\u003e 'Faction',\n    'description' =\u003e 'A faction in the Star Wars saga',\n    'fields' =\u003e function() use ($shipConnection) {\n        return [\n            'id' =\u003e Relay::globalIdField(),\n            'name' =\u003e [\n                'type' =\u003e Type::string(),\n                'description' =\u003e 'The name of the faction.'\n            ],\n            'ships' =\u003e [\n                'type' =\u003e $shipConnection['connectionType'],\n                'description' =\u003e 'The ships used by the faction.',\n                'args' =\u003e Relay::connectionArgs(),\n                'resolve' =\u003e function($faction, $args) {\n                    // Map IDs from faction back to ships\n                    $data = array_map(function($id) {\n                        return StarWarsData::getShip($id);\n                    }, $faction['ships']);\n                    return Relay::connectionFromArray($data, $args);\n                }\n            ]\n        ];\n    },\n    'interfaces' =\u003e [$nodeDefinition['nodeInterface']]\n]);\n```\n\nThis shows adding a `ships` field to the `Faction` object that is a connection.\nIt uses `connectionDefinitions({nodeType: shipType})` to create the connection\ntype, adds `connectionArgs` as arguments on this function, and then implements\nthe resolve function by passing the array of ships and the arguments to\n`connectionFromArray`.\n\n### Object Identification\n\nHelper functions are provided for both building the GraphQL types\nfor nodes and for implementing global IDs around local IDs.\n\n - `Relay::nodeDefinitions` returns the `Node` interface that objects can implement,\nand returns the `node` root field to include on the query type. To implement\nthis, it takes a function to resolve an ID to an object, and to determine\nthe type of a given object.\n - `Relay::toGlobalId` takes a type name and an ID specific to that type name,\nand returns a \"global ID\" that is unique among all types.\n - `Relay::fromGlobalId` takes the \"global ID\" created by `toGlobalID`, and returns\nthe type name and ID used to create it.\n - `Relay::globalIdField` creates the configuration for an `id` field on a node.\n - `Relay::pluralIdentifyingRootField` creates a field that accepts a list of\nnon-ID identifiers (like a username) and maps then to their corresponding\nobjects.\n\nAn example usage of these methods from the [test schema](tests/StarWarsSchema.php):\n\n```php\n$nodeDefinition = Relay::nodeDefinitions(\n    // The ID fetcher definition\n    function ($globalId) {\n        $idComponents = Relay::fromGlobalId($globalId);\n        if ($idComponents['type'] === 'Faction'){\n            return StarWarsData::getFaction($idComponents['id']);\n        } else if ($idComponents['type'] === 'Ship'){\n            return StarWarsData::getShip($idComponents['id']);\n        } else {\n            return null;\n        }\n    },\n    // Type resolver\n    function ($object) {\n        return isset($object['ships']) ? self::getFactionType() : self::getShipType();\n    }\n);\n\n$factionType = new ObjectType([\n    'name' =\u003e 'Faction',\n    'description' =\u003e 'A faction in the Star Wars saga',\n    'fields' =\u003e function() use ($shipConnection) {\n        return [\n            'id' =\u003e Relay::globalIdField(),\n            'name' =\u003e [\n                'type' =\u003e Type::string(),\n                'description' =\u003e 'The name of the faction.'\n            ],\n            'ships' =\u003e [\n                'type' =\u003e $shipConnection['connectionType'],\n                'description' =\u003e 'The ships used by the faction.',\n                'args' =\u003e Relay::connectionArgs(),\n                'resolve' =\u003e function($faction, $args) {\n                    // Map IDs from faction back to ships\n                    $data = array_map(function($id) {\n                        return StarWarsData::getShip($id);\n                    }, $faction['ships']);\n                    return Relay::connectionFromArray($data, $args);\n                }\n            ]\n        ];\n    },\n    'interfaces' =\u003e [$nodeDefinition['nodeInterface']]\n]);\n\n$queryType = new ObjectType([\n    'name' =\u003e 'Query',\n    'fields' =\u003e function () use ($nodeDefinition) {\n        return [\n            'node' =\u003e $nodeDefinition['nodeField']\n        ];\n    },\n]);\n```\n\nThis uses `Relay::nodeDefinitions` to construct the `Node` interface and the `node`\nfield; it uses `fromGlobalId` to resolve the IDs passed in in the implementation\nof the function mapping ID to object. It then uses the `Relay::globalIdField` method to\ncreate the `id` field on `Faction`, which also ensures implements the\n`nodeInterface`. Finally, it adds the `node` field to the query type, using the\n`nodeField` returned by `Relay::nodeDefinitions`.\n\n### Mutations\n\nA helper function is provided for building mutations with\nsingle inputs and client mutation IDs.\n\n - `Relay::mutationWithClientMutationId` takes a name, input fields, output fields,\nand a mutation method to map from the input fields to the output fields,\nperforming the mutation along the way. It then creates and returns a field\nconfiguration that can be used as a top-level field on the mutation type.\n\nAn example usage of these methods from the [test schema](tests/StarWarsSchema.php):\n\n```php\n$shipMutation = Relay::mutationWithClientMutationId([\n    'name' =\u003e 'IntroduceShip',\n    'inputFields' =\u003e [\n        'shipName' =\u003e [\n            'type' =\u003e Type::nonNull(Type::string())\n        ],\n        'factionId' =\u003e [\n            'type' =\u003e Type::nonNull(Type::id())\n        ]\n    ],\n    'outputFields' =\u003e [\n        'ship' =\u003e [\n            'type' =\u003e $shipType,\n            'resolve' =\u003e function ($payload) {\n                return StarWarsData::getShip($payload['shipId']);\n            }\n        ],\n        'faction' =\u003e [\n            'type' =\u003e $factionType,\n            'resolve' =\u003e function ($payload) {\n                return StarWarsData::getFaction($payload['factionId']);\n            }\n        ]\n    ],\n    'mutateAndGetPayload' =\u003e function ($input) {\n        $newShip = StarWarsData::createShip($input['shipName'], $input['factionId']);\n        return [\n            'shipId' =\u003e $newShip['id'],\n            'factionId' =\u003e $input['factionId']\n        ];\n    }\n]);\n\n$mutationType = new ObjectType([\n    'name' =\u003e 'Mutation',\n    'fields' =\u003e function () use ($shipMutation) {\n        return [\n            'introduceShip' =\u003e $shipMutation\n        ];\n    }\n]);\n```\n\nThis code creates a mutation named `IntroduceShip`, which takes a faction\nID and a ship name as input. It outputs the `Faction` and the `Ship` in\nquestion. `mutateAndGetPayload` then gets an object with a property for\neach input field, performs the mutation by constructing the new ship, then\nreturns an object that will be resolved by the output fields.\n\nOur mutation type then creates the `introduceShip` field using the return\nvalue of `Relay::mutationWithClientMutationId`.\n\n## Contributing\n\nAfter cloning this repo, ensure dependencies are installed by running:\n\n```sh\ncomposer install\n```\n\nAfter developing, the full test suite can be evaluated by running:\n\n```sh\nbin/phpunit tests\n```\n","funding_links":[],"categories":["Libraries","Implementations"],"sub_categories":["PHP Libraries","PHP"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivome%2Fgraphql-relay-php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivome%2Fgraphql-relay-php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivome%2Fgraphql-relay-php/lists"}