{"id":13499279,"url":"https://github.com/digiaonline/graphql-php","last_synced_at":"2025-03-29T04:30:53.246Z","repository":{"id":29448273,"uuid":"120626604","full_name":"digiaonline/graphql-php","owner":"digiaonline","description":"A PHP7 implementation of the GraphQL specification.","archived":true,"fork":false,"pushed_at":"2022-05-04T10:49:18.000Z","size":1727,"stargazers_count":217,"open_issues_count":0,"forks_count":11,"subscribers_count":21,"default_branch":"main","last_synced_at":"2024-05-22T19:28:56.443Z","etag":null,"topics":["api","graphql","php","php-library","php7"],"latest_commit_sha":null,"homepage":"https://facebook.github.io/graphql/","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/digiaonline.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-02-07T14:37:21.000Z","updated_at":"2024-05-20T10:19:03.000Z","dependencies_parsed_at":"2022-08-08T09:30:17.595Z","dependency_job_id":null,"html_url":"https://github.com/digiaonline/graphql-php","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digiaonline%2Fgraphql-php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digiaonline%2Fgraphql-php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digiaonline%2Fgraphql-php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digiaonline%2Fgraphql-php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/digiaonline","download_url":"https://codeload.github.com/digiaonline/graphql-php/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245918340,"owners_count":20693691,"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":["api","graphql","php","php-library","php7"],"created_at":"2024-07-31T22:00:31.796Z","updated_at":"2025-03-29T04:30:52.710Z","avatar_url":"https://github.com/digiaonline.png","language":"PHP","funding_links":["https://opencollective.com/graphql-php"],"categories":["Libraries"],"sub_categories":["PHP Libraries"],"readme":"# GraphQL\n\n[![GitHub Actions status](https://github.com/digiaonline/graphql-php/workflows/Test/badge.svg)](https://github.com/digiaonline/graphql-php/actions)\n[![Coverage Status](https://coveralls.io/repos/github/digiaonline/graphql-php/badge.svg?branch=main)](https://coveralls.io/github/digiaonline/graphql-php?branch=main)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/digiaonline/graphql-php/badges/quality-score.png?b=main)](https://scrutinizer-ci.com/g/digiaonline/graphql-php/?branch=main)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/digiaonline/graphql-php/main/LICENSE)\n[![Backers on Open Collective](https://opencollective.com/graphql-php/backers/badge.svg)](#backers) \n[![Sponsors on Open Collective](https://opencollective.com/graphql-php/sponsors/badge.svg)](#sponsors) \n\nThis is a PHP implementation of the [GraphQL specification](https://facebook.github.io/graphql/) based on the \nJavaScript [reference implementation](https://github.com/graphql/graphql-js).\n\n## Related projects\n\n- [DateTime scalar](https://github.com/digiaonline/graphql-datetime-scalar-php)\n- [Relay support](https://github.com/digiaonline/graphql-relay-php)\n\n## Requirements\n\n- PHP version \u003e= 7.1\n- ext-mbstring\n\n## Table of contents\n\n- [Installation](#installation)\n- [Example](#example)\n- [Creating a schema](#creating-a-schema)\n  - [Resolver registry](#resolver-registry)\n  - [Resolver middleware](#resolver-middleware)\n- [Execution](#execution)\n  - [Queries](#queries)\n  - [Resolvers](#resolvers)\n    - [The N+1 problem](#the-n1-problem)\n  - [Variables](#variables)\n  - [Context](#context)\n- [Scalars](#scalars)\n  - [Custom scalars](#custom-scalars)\n- [Advanced usage](#advanced-usage)\n- [Integration](#integration)\n  - [Laravel](#laravel)\n\n## Installation\n\nRun the following command to install the package through Composer:\n\n```sh\ncomposer require digiaonline/graphql\n```\n\n## Example\n\nHere is a simple example that demonstrates how to build an executable schema from a GraphQL schema file that contains \nthe Schema Definition Language (SDL) for a Star Wars-themed schema (for the schema definition itself, see below). In \nthis example we use that SDL to build an executable schema and use it to query for the name of the hero. The result \nof that query is an associative array with a structure that resembles the query we ran.\n\n```php\nuse Digia\\GraphQL\\Language\\FileSourceBuilder;\nuse function Digia\\GraphQL\\buildSchema;\nuse function Digia\\GraphQL\\graphql;\n\n$sourceBuilder = new FileSourceBuilder(__DIR__ . '/star-wars.graphqls');\n\n$schema = buildSchema($sourceBuilder-\u003ebuild(), [\n    'Query' =\u003e [\n        'hero' =\u003e function ($rootValue, $arguments) {\n            return getHero($arguments['episode'] ?? null);\n        },\n    ],\n]);\n\n$result = graphql($schema, '\nquery HeroNameQuery {\n  hero {\n    name\n  }\n}');\n\n\\print_r($result);\n```\n\nThe script above produces the following output:\n\n```php\nArray\n(\n    [data] =\u003e Array\n    (\n        [hero] =\u003e Array\n        (\n            [name] =\u003e \"R2-D2\"\n        )\n        \n    )\n    \n)\n```\n\nThe GraphQL schema file used in this example contains the following:\n\n```graphql schema\nschema {\n    query: Query\n}\n\ntype Query {\n    hero(episode: Episode): Character\n    human(id: String!): Human\n    droid(id: String!): Droid\n}\n\ninterface Character {\n    id: String!\n    name: String\n    friends: [Character]\n    appearsIn: [Episode]\n}\n\ntype Human implements Character {\n    id: String!\n    name: String\n    friends: [Character]\n    appearsIn: [Episode]\n    homePlanet: String\n}\n\ntype Droid implements Character {\n    id: String!\n    name: String\n    friends: [Character]\n    appearsIn: [Episode]\n    primaryFunction: String\n}\n\nenum Episode { NEWHOPE, EMPIRE, JEDI }\n```\n\n## Creating a schema\n\nIn order to execute queries against your GraphQL API, you first need to define the structure of your API. This is done\nby creating a schema. There are two ways to do this, you can either do it using SDL or you can do it programmatically. \nHowever, we strongly encourage you to use SDL, because it is easier to work with. To make an executable schema from \nSDL you need to call the `buildSchema` function.\n \nThe `buildSchema` function takes three arguments:\n\n- `$source` The schema definition (SDL) as a `Source` instance\n- `$resolverRegistry` An associative array or a `ResolverRegistry` instance that contains all resolvers\n- `$options` The options for building the schema, which also includes custom types and directives\n\nTo create the `Source` instance you can use the provided `FileSourceBuilder` or `MultiFileSourceBuilder` classes.\n\n### Resolver registry\n\nThe resolver registry is essentially a flat map with the type names as its keys and their corresponding resolver \ninstances as its values. For smaller projects you can use an associative array and lambda functions to define your \nresolver registry. However, in larger projects we suggest that you implement your own resolvers instead. You can read \nmore about resolvers under the [Resolvers](#resolvers) section.\n\nAssociative array example:\n\n```php\n$schema = buildSchema($source, [\n    'Query' =\u003e [\n        'hero' =\u003e function ($rootValue, $arguments) {\n            return getHero($arguments['episode'] ?? null);\n        },\n    ],\n]);\n```\n\nResolver class example:\n\n```php\n$schema = buildSchema($source, [\n    'Query' =\u003e [\n        'hero' =\u003e new HeroResolver(),\n    ],\n]);\n```\n\n### Resolver middleware\n\nIf you find yourself writing the same logic in multiple resolvers you should consider using middleware. Resolver \nmiddleware allow you to efficiently manage functionality across multiple resolvers.\n\nBefore middleware example:\n\n```php\n$resolverRegistry = new ResolverRegristry([\n    'Query' =\u003e [\n        'hero' =\u003e function ($rootValue, $arguments) {\n            return getHero($arguments['episode'] ?? null);\n        },\n    ],\n], [\n    'middleware' =\u003e [new BeforeMiddleware()],\n]);\n$schema = buildSchema($source, $resolverRegistry);\n```\n\n```php\nclass BeforeMiddleware implements ResolverMiddlewareInterface\n{\n    public function resolve(callable $resolveCallback, $rootValue, array $arguments, $context, ResolveInfo $info) {\n        $newRootValue = $this-\u003edoSomethingBefore();\n        return $resolveCallback($newRootValue, $arguments, $context, $info);\n    }\n}\n```\n\nAfter middleware example:\n\n```php\n$resolverRegistry = new ResolverRegristry([\n    'Query' =\u003e [\n        'hero' =\u003e function ($rootValue, $arguments) {\n            return getHero($arguments['episode'] ?? null);\n        },\n    ],\n], [\n    'middleware' =\u003e [new AfterMiddleware()],\n]);\n$schema = buildSchema($source, $resolverRegistry);\n```\n\n```php\nclass AfterMiddleware implements ResolverMiddlewareInterface\n{\n    public function resolve(callable $resolveCallback, $rootValue, array $arguments, $context, ResolveInfo $info) {\n        $result = $resolveCallback($rootValue, $arguments, $context, $info);\n        $this-\u003edoSomethingAfter();\n        return $result;\n    }\n}\n```\n\nResolver middleware can be useful for a number of things; such as logging, input sanitization, performance \nmeasurement, authorization and caching.\n\nIf you want to learn more about schemas you can refer to the [specification](https://graphql.org/learn/schema/).\n\n## Execution\n\n### Queries\n\nTo execute a query against your schema you need to call the `graphql` function and pass it your schema and the query \nyou wish to execute. You can also run _mutations_ and _subscriptions_ by changing your query.\n\n```php\n$query = '\nquery HeroNameQuery {\n  hero {\n    name\n  }\n}';\n\n$result = graphql($schema, $query);\n```\n\nIf you want to learn more about queries you can refer to the [specification](https://graphql.org/learn/queries/).\n\n### Resolvers\n\nEach type in a schema has a resolver associated with it that allows for resolving the actual value. However, most \ntypes do not need a custom resolver, because they can be resolved using the default resolver. Usually these resolvers \nare lambda functions, but you can also define your own resolvers by extending `AbstractTypeResolver` or `AbstractFieldResolver`. Alternatively you can also implement the `ResolverInterface` directly.\n\nA resolver function receives four arguments:\n\n- `$rootValue` The parent object, which can also be `null` in some cases\n- `$arguments` The arguments provided to the field in the query\n- `$context` A value that is passed to every resolver that can hold important contextual information\n- `$info` A value which holds field-specific information relevant to the current query\n\nLambda function example:\n\n```php\nfunction ($rootValue, array $arguments, $context, ResolveInfo $info): string {\n    return [\n        'type'       =\u003e 'Human',\n        'id'         =\u003e '1000',\n        'name'       =\u003e 'Luke Skywalker',\n        'friends'    =\u003e ['1002', '1003', '2000', '2001'],\n        'appearsIn'  =\u003e ['NEWHOPE', 'EMPIRE', 'JEDI'],\n        'homePlanet' =\u003e 'Tatooine',\n    ];\n}\n``` \n\nType resolver example:\n\n```php\nclass HumanResolver extends AbstractTypeResolver\n{\n    public function resolveName($rootValue, array $arguments, $context, ResolveInfo $info): string\n    {\n        return $rootValue['name'];\n    }\n}\n```\n\nField resolver example:\n\n```php\nclass NameResolver extends AbstractFieldResolver\n{\n    public function resolve($rootValue, array $arguments, $context, ResolveInfo $info): string\n    {\n       return $rootValue['name'];\n    }\n}\n```\n\n#### The N+1 problem\n\nThe resolver function can return a value, a [promise](https://github.com/reactphp/promise) or an array of promises. \nThis resolver function below illustrates how to use promise to solve the N+1 problem, the full example can be found in \nthis [test case](/tests/Functional/Execution/DeferredResolverTest.php).\n\n```php\n$movieType = newObjectType([\n    'fields' =\u003e [\n        'title'    =\u003e ['type' =\u003e stringType()],\n        'director' =\u003e [\n            'type'    =\u003e $directorType,\n            'resolve' =\u003e function ($movie, $args) {\n                DirectorBuffer::add($movie['directorId']);\n                \n                return new Promise(function (callable $resolve, callable $reject) use ($movie) {\n                    DirectorBuffer::loadBuffered();\n                    $resolve(DirectorBuffer::get($movie['directorId']));\n                });\n            }\n        ]\n    ]\n]);\n```\n\n### Variables\n\nYou can pass in variables when executing a query by passing them to the `graphql` function.\n\n```php\n$query = '\nquery HeroNameQuery($id: ID!) {\n  hero(id: $id) {\n    name\n  }\n}';\n\n$variables = ['id' =\u003e '1000'];\n\n$result = graphql($schema, $query, null, null, $variables);\n```\n\n### Context\n\nIn case you need to pass in some important contextual information to your queries you can use the `$contextValues` \nargument on `graphql` to do so. This data will be passed to all of your resolvers as the `$context` argument.\n\n```php\n$contextValues = [\n    'currentlyLoggedInUser' =\u003e $currentlyLoggedInUser,\n];\n\n$result = graphql($schema, $query, null, $contextValues, $variables);\n```\n\n## Scalars\n\nThe leaf nodes in a schema are called scalars and each scalar resolves to some concrete data. The built-in, or \nspecified scalars in GraphQL are the following:\n\n- Boolean\n- Float\n- Int\n- ID\n- String\n\n### Custom scalars\n\nIn addition to the specified scalars you can also define your own custom scalars and let your schema know about \nthem by passing them to the `buildSchema` function as part of its `$options` argument. \n\nCustom Date scalar type example:\n\n```php\n$dateType = newScalarType([\n    'name'         =\u003e 'Date',\n    'serialize'    =\u003e function ($value) {\n        if ($value instanceof DateTime) {\n            return $value-\u003eformat('Y-m-d');\n        }\n        return null;\n    },\n    'parseValue'   =\u003e function ($value) {\n        if (\\is_string($value)){\n            return new DateTime($value);\n        }\n        return null;\n    },\n    'parseLiteral' =\u003e function ($node) {\n        if ($node instanceof StringValueNode) {\n            return new DateTime($node-\u003egetValue());\n        }\n        return null;\n    },\n]);\n\n$schema = buildSchema($source, [\n    'Query' =\u003e QueryResolver::class,\n    [\n        'types' =\u003e [$dateType],\n    ],\n]);\n```\n\nEvery scalar has to be coerced, which is done by three different functions. The `serialize` function converts a \nPHP value into the corresponding output value. The`parseValue` function converts a variable input value into the\ncorresponding PHP value and the `parseLiteral` function converts an AST literal into the corresponding PHP value.\n\n## Advanced usage\n\nIf you are looking for something that isn't yet covered by this documentation your best bet is to take a look at the \n[tests](./tests) in this project. You'll be surprised how many examples you'll find there.\n\n## Integration\n\n### Laravel\n\nHere is an example that demonstrates how you can use this library in your Laravel project. You need an application \nservice to expose this library to your application, a service provider to register that service, a controller and a \nroute for handling the GraphQL POST requests.\n\n**app/GraphQL/GraphQLService.php**\n```php\nclass GraphQLService\n{\n    private $schema;\n\n    public function __construct(Schema $schema)\n    {\n        $this-\u003eschema = $schema;\n    }\n\n    public function executeQuery(string $query, array $variables, ?string $operationName): array\n    {\n        return graphql($this-\u003eschema, $query, null, null, $variables, $operationName);\n    }\n}\n```\n\n**app/GraphQL/GraphQLServiceProvider.php**\n```php\nclass GraphQLServiceProvider\n{\n    public function register()\n    {\n        $this-\u003eapp-\u003esingleton(GraphQLService::class, function () {\n            $schemaDef = \\file_get_contents(__DIR__ . '/schema.graphqls');\n\n            $executableSchema = buildSchema($schemaDef, [\n                'Query' =\u003e QueryResolver::class,\n            ]);\n\n            return new GraphQLService($executableSchema);\n        });\n    }\n}\n```\n\n**app/GraphQL/GraphQLController.php**\n```php\nclass GraphQLController extends Controller\n{\n    private $graphqlService;\n\n    public function __construct(GraphQLService $graphqlService)\n    {\n        $this-\u003egraphqlService = $graphqlService;\n    }\n\n    public function handle(Request $request): JsonResponse\n    {\n        $query         = $request-\u003eget('query');\n        $variables     = $request-\u003eget('variables') ?? [];\n        $operationName = $request-\u003eget('operationName');\n\n        $result = $this-\u003egraphqlService-\u003eexecuteQuery($query, $variables, $operationName);\n\n        return response()-\u003ejson($result);\n    }\n}\n```\n\n**routes/api.php**\n```php\nRoute::post('/graphql', 'app\\GraphQL\\GraphQLController@handle');\n```\n\n## Contributors\n\nThis project exists thanks to all the people who contribute. [Contribute](.github/CONTRIBUTING.md).\n\n\u003ca href=\"graphs/contributors\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/contributors.svg?width=890\u0026button=false\" /\u003e\u003c/a\u003e\n\n\n## Backers\n\nThank you to all our backers! 🙏 [Become a backer](https://opencollective.com/graphql-php#backer)\n\n\u003ca href=\"https://opencollective.com/graphql-php#backers\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/backers.svg?width=890\"\u003e\u003c/a\u003e\n\n## Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor](https://opencollective.com/graphql-php#sponsor)\n\n\u003ca href=\"https://opencollective.com/graphql-php/sponsor/0/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/sponsor/0/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-php/sponsor/1/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/sponsor/1/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-php/sponsor/2/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/sponsor/2/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-php/sponsor/3/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/sponsor/3/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-php/sponsor/4/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/sponsor/4/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-php/sponsor/5/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/sponsor/5/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-php/sponsor/6/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/sponsor/6/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-php/sponsor/7/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/sponsor/7/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-php/sponsor/8/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/sponsor/8/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/graphql-php/sponsor/9/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/graphql-php/sponsor/9/avatar.svg\"\u003e\u003c/a\u003e\n\n## License\n\nSee [LICENCE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigiaonline%2Fgraphql-php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigiaonline%2Fgraphql-php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigiaonline%2Fgraphql-php/lists"}