{"id":13562464,"url":"https://github.com/API-Skeletons/doctrine-graphql","last_synced_at":"2025-04-03T18:33:43.359Z","repository":{"id":41973123,"uuid":"277443087","full_name":"API-Skeletons/doctrine-graphql","owner":"API-Skeletons","description":"GraphQL Type Driver for Doctrine ORM","archived":false,"fork":false,"pushed_at":"2024-09-03T21:31:20.000Z","size":1247,"stargazers_count":11,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-12-18T05:43:12.941Z","etag":null,"topics":["doctrine","graphql"],"latest_commit_sha":null,"homepage":"","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/API-Skeletons.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-06T04:36:09.000Z","updated_at":"2023-12-21T02:53:39.000Z","dependencies_parsed_at":"2024-11-04T14:34:16.720Z","dependency_job_id":"64fee6aa-2229-4365-a76a-2d6338078df1","html_url":"https://github.com/API-Skeletons/doctrine-graphql","commit_stats":{"total_commits":527,"total_committers":1,"mean_commits":527.0,"dds":0.0,"last_synced_commit":"02b0a6e8e7eea9328328a74699b80598d915158b"},"previous_names":[],"tags_count":57,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/API-Skeletons%2Fdoctrine-graphql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/API-Skeletons%2Fdoctrine-graphql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/API-Skeletons%2Fdoctrine-graphql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/API-Skeletons%2Fdoctrine-graphql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/API-Skeletons","download_url":"https://codeload.github.com/API-Skeletons/doctrine-graphql/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247057078,"owners_count":20876509,"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":["doctrine","graphql"],"created_at":"2024-08-01T13:01:08.966Z","updated_at":"2025-04-03T18:33:38.332Z","avatar_url":"https://github.com/API-Skeletons.png","language":"PHP","funding_links":[],"categories":["PHP"],"sub_categories":[],"readme":"GraphQL Type Driver for Doctrine ORM\n====================================\n\nThis project has been retired in favor of [API-Skeletons/doctrine-orm-graphql](https://github.com/API-Skeletons/doctrine-orm-graphql)\n===================================\n\nSee the [upgrade guide](https://doctrine-orm-graphql.apiskeletons.dev/en/latest/upgrade.html) if you're a user of the 8.x branch.\n\nAll the original documentation can be found below.\n\n\n\n\n[![Build Status](https://github.com/API-Skeletons/doctrine-graphql/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/API-Skeletons/doctrine-graphql/actions/workflows/continuous-integration.yml?query=branch%3Amain)\n[![Code Coverage](https://codecov.io/gh/API-Skeletons/doctrine-graphql/branch/main/graphs/badge.svg)](https://codecov.io/gh/API-Skeletons/doctrine-graphql/branch/main)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/API-Skeletons/doctrine-graphql/badges/quality-score.png?b=main)](https://scrutinizer-ci.com/g/API-Skeletons/doctrine-graphql/?branch=main)\n[![PHP Version](https://img.shields.io/badge/PHP-8.0%2b-blue)](https://img.shields.io/badge/PHP-8.0%2b-blue)\n[![Total Downloads](https://poser.pugx.org/api-skeletons/doctrine-graphql/downloads)](//packagist.org/packages/api-skeletons/doctrine-graphql)\n[![License](https://poser.pugx.org/api-skeletons/doctrine-graphql/license)](//packagist.org/packages/api-skeletons/doctrine-graphql)\n\n\nThis library provides a framework agnostic GraphQL driver for Doctrine ORM for use with [webonyx/graphql-php](https://github.com/webonyx/graphql-php).  Configuration is available from zero to verbose.  Multiple configurations for multiple drivers are supported.\n\n[Detailed documentation](https://apiskeletons-doctrine-graphql.readthedocs.io/en/latest/) is available.\n\nFor an example application post to `https://graphql.lcdb.org/`\n\n\nLibrary Highlights\n------------------\n\n* Uses [PHP 8 Attributes](https://apiskeletons-doctrine-graphql.readthedocs.io/en/latest/attributes.html)\n* [Multiple independent configurations](https://apiskeletons-doctrine-graphql.readthedocs.io/en/latest/config.html)\n* Support for all default [Doctrine Types](https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html) \u0026 custom types\n* Support for the [GraphQL Complete Connection Model](https://graphql.org/learn/pagination/#complete-connection-model)\n* Supports [filtering of sub-collections](https://apiskeletons-doctrine-graphql.readthedocs.io/en/latest/queries.html)\n* [Events](https://github.com/API-Skeletons/doctrine-graphql#events) for modifying queries and entity types\n* Uses the [Doctrine Laminas Hydrator](https://www.doctrine-project.org/projects/doctrine-laminas-hydrator/en/3.1/index.html) for extraction\n* Conforms to the [Doctrine Coding Standard](https://www.doctrine-project.org/projects/doctrine-coding-standard/en/9.0/index.html)\n\nInstallation\n------------\n\nRun the following to install this library using [Composer](https://getcomposer.org/):\n\n```bash\ncomposer require api-skeletons/doctrine-graphql\n```\n\nEntity Relationship Diagram\n---------------------------\n\n[This Entity Relationship Diagram](https://raw.githubusercontent.com/API-Skeletons/doctrine-graphql/master/test/doctrine-graphql.skipper), created with [Skipper](https://skipper18.com), is used for the query examples below and testing this library.\n\n![Entity Relationship Diagram](https://raw.githubusercontent.com/API-Skeletons/doctrine-graphql/master/test/doctrine-graphql.png)\n\n\nQuick Start\n-----------\n\nAdd attributes to your Doctrine entities\n\n```php\nuse ApiSkeletons\\Doctrine\\GraphQL\\Attribute as GraphQL;\n\n#[GraphQL\\Entity]\nclass Artist \n{\n    #[GraphQL\\Field]\n    public $id;\n    \n    #[GraphQL\\Field]\n    public $name;\n    \n    #[GraphQL\\Association]\n    public $performances;\n}\n\n#[GraphQL\\Entity]\nclass Performance\n{\n    #[GraphQL\\Field]\n    public $id;\n    \n    #[GraphQL\\Field]\n    public $venue;\n    \n    /**\n     * Not all fields need attributes.\n     * Only add attribues to fields you want available in GraphQL\n     */\n    public $city;\n}\n```\n\nCreate the driver and GraphQL schema\n\n```php\nuse ApiSkeletons\\Doctrine\\GraphQL\\Driver;\nuse Doctrine\\ORM\\EntityManager;\nuse GraphQL\\Type\\Definition\\ObjectType;\nuse GraphQL\\Type\\Definition\\Type;\nuse GraphQL\\Type\\Schema;\n\n$driver = new Driver($entityManager);\n\n$schema = new Schema([\n    'query' =\u003e new ObjectType([\n        'name' =\u003e 'query',\n        'fields' =\u003e [\n            'artists' =\u003e [\n                'type' =\u003e $driver-\u003econnection($driver-\u003etype(Artist::class)),\n                'args' =\u003e [\n                    'filter' =\u003e $driver-\u003efilter(Artist::class),\n                    'pagination' =\u003e $driver-\u003epagination(),\n                ],\n                'resolve' =\u003e $driver-\u003eresolve(Artist::class),\n            ],\n        ],\n    ]),\n    'mutation' =\u003e new ObjectType([\n        'name' =\u003e 'mutation',\n        'fields' =\u003e [\n            'artistUpdateName' =\u003e [\n                'type' =\u003e $driver-\u003etype(Artist::class),\n                'args' =\u003e [\n                    'id' =\u003e Type::nonNull(Type::id()),\n                    'input' =\u003e Type::nonNull($driver-\u003einput(Artist::class, ['name'])),\n                ],\n                'resolve' =\u003e function ($root, $args) use ($driver): Artist {\n                    $artist = $driver-\u003eget(EntityManager::class)\n                        -\u003egetRepository(Artist::class)\n                        -\u003efind($args['id']);\n\n                    $artist-\u003esetName($args['input']['name']);\n                    $driver-\u003eget(EntityManager::class)-\u003eflush();\n\n                    return $artist;\n                },\n            ],\n        ],\n    ]),\n]);\n```\n\nRun GraphQL queries\n\n```php\nuse GraphQL\\GraphQL;\n\n$query = '{ \n    artists { \n        edges { \n            node { \n                id \n                name \n                performances { \n                    edges { \n                        node { \n                            venue \n                        } \n                    } \n                } \n            } \n        } \n    }\n}';\n\n$result = GraphQL::executeQuery(\n    schema: $schema,\n    source: $query,\n    variableValues: null,\n    operationName: null\n);\n\n$output = $result-\u003etoArray();\n```\n\nRun GraphQL mutations\n\n```php\nuse GraphQL\\GraphQL;\n\n$query = 'mutation ArtistUpdateName($id: Int!, $name: String!) {\n    artistUpdateName(id: $id, input: { name: $name }) {\n        id\n        name\n    }\n}';\n\n$result = GraphQL::executeQuery(\n    schema: $schema,\n    source: $query,\n    variableValues: ['id' =\u003e 1, 'name' =\u003e 'newName'],\n    operationName: 'ArtistUpdateName'\n);\n\n$output = $result-\u003etoArray();\n```\n\nFiltering\n---------\n\nFor every attributed field and every attributed association, filters are available in your\nGraphQL query.\n\nExample\n\n```gql\n{\n  artists ( filter: { name: { contains: \"dead\" } } ) {\n    edges {\n      node {\n        id\n        name\n        performances ( filter: { venue: { eq: \"The Fillmore\" } } ) {\n          edges { \n            node {\n              venue\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nEach field has their own set of filters.  Most fields have the following:\n\n* eq - Equals.\n* neq - Not equals.\n* lt - Less than.\n* lte - Less than or equal to.\n* gt - Greater than.\n* gte - Greater than or equal to.\n* isnull - Is null.  If value is true, the field must be null.  If value is false, the field must not be null.\n* between - Between.  Identical to using gte \u0026 lte on the same field.  Give values as `low, high`.\n* in - Exists within a list of comma-delimited values.\n* notin - Does not exist within a list of comma-delimited values.\n* startwith - A like query with a wildcard on the right side of the value.\n* endswith - A like query with a wildcard on the left side of the value.\n* contains - A like query.\n\n\nEvents\n------\n\n### Filter Query Builder\n\nYou may modify the query builder used to resolve any connection by subscribing to events.\nEach connection may have a unique event name.  `Entity::class . '.filterQueryBuilder'` is recommended.\nPass as the second parameter to `$driver-\u003eresolve()`.\n\n```php\nuse ApiSkeletons\\Doctrine\\GraphQL\\Event\\FilterQueryBuilder;\nuse App\\ORM\\Entity\\Artist;\nuse GraphQL\\Type\\Definition\\ObjectType;\nuse GraphQL\\Type\\Schema;\nuse League\\Event\\EventDispatcher;\n\n$schema = new Schema([\n  'query' =\u003e new ObjectType([\n      'name' =\u003e 'query',\n      'fields' =\u003e [\n          'artists' =\u003e [\n              'type' =\u003e $driver-\u003econnection($driver-\u003etype(Artist::class)),\n              'args' =\u003e [\n                  'filter' =\u003e $driver-\u003efilter(Artist::class),\n                  'pagination' =\u003e $driver-\u003epagination(),\n              ],\n              'resolve' =\u003e $driver-\u003eresolve(Artist::class, Artist::class . '.filterQueryBuilder'),\n          ],\n      ],\n  ]),\n]);\n\n$driver-\u003eget(EventDispatcher::class)-\u003esubscribeTo(Artist::class . '.filterQueryBuilder',\n    function(FilterQueryBuilder $event) {\n        $event-\u003egetQueryBuilder()\n            -\u003einnerJoin('entity.user', 'user')\n            -\u003eandWhere($event-\u003egetQueryBuilder()-\u003eexpr()-\u003eeq('user.id', ':userId'))\n            -\u003esetParameter('userId', currentUser()-\u003egetId())\n            ;\n    }\n);\n```\n\n### Filter Association Criteria\n\nYou may modify the criteria object used to filter associations.  For instance, if you use soft \ndeletes then you would want to filter out deleted rows from an association.\n\n```php\nuse ApiSkeletons\\Doctrine\\GraphQL\\Attribute as GraphQL;\nuse ApiSkeletons\\Doctrine\\GraphQL\\Event\\FilterCriteria;\nuse App\\ORM\\Entity\\Artist;\nuse League\\Event\\EventDispatcher;\n\n#[GraphQL\\Entity]\nclass Artist \n{\n    #[GraphQL\\Field]\n    public $id;\n    \n    #[GraphQL\\Field]\n    public $name;\n    \n    #[GraphQL\\Association(filterCriteriaEventName: self::class . '.performances.filterCriteria')]\n    public $performances;\n}\n\n// Add a listener to your driver\n$driver-\u003eget(EventDispatcher::class)-\u003esubscribeTo(\n    Artist::class . '.performances.filterCriteria',\n    function (FilterCriteria $event): void {\n        $event-\u003egetCriteria()-\u003eandWhere(\n            $event-\u003egetCriteria()-\u003eexpr()-\u003eeq('isDeleted', false)\n        );\n    },\n);\n```\n\n\n### Entity ObjectType Definition\n\nYou may modify the array used to define an entity type before it is created. This can be used for generated data and the like. \nYou must attach to events before defining your GraphQL schema.  See the [detailed documentation](https://apiskeletons-doctrine-graphql.readthedocs.io/en/latest/events.html#modify-an-entity-definition) for details.\n\n```php\nuse ApiSkeletons\\Doctrine\\GraphQL\\Driver;\nuse ApiSkeletons\\Doctrine\\GraphQL\\Event\\EntityDefinition;\nuse App\\ORM\\Entity\\Artist;\nuse GraphQL\\Type\\Definition\\ResolveInfo;\nuse GraphQL\\Type\\Definition\\Type;\nuse League\\Event\\EventDispatcher;\n\n$driver = new Driver($entityManager);\n\n$driver-\u003eget(EventDispatcher::class)-\u003esubscribeTo(\n    Artist::class . '.definition',\n    static function (EntityDefinition $event): void {\n        $definition = $event-\u003egetDefinition();\n\n        // In order to modify the fields you must resovle the closure\n        $fields = $definition['fields']();\n\n        // Add a custom field to show the name without a prefix of 'The'\n        $fields['nameUnprefix'] = [\n            'type' =\u003e Type::string(),\n            'description' =\u003e 'A computed dynamically added field',\n            'resolve' =\u003e static function ($objectValue, array $args, $context, ResolveInfo $info): mixed {\n                return trim(str_replace('The', '', $objectValue-\u003egetName()));\n            },\n        ];\n\n        $definition['fields'] = $fields;\n    }\n);\n```\n\n\nFurther Reading\n---------------\n\n[Detailed documentation](https://apiskeletons-doctrine-graphql.readthedocs.io/en/latest/)\nis available.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAPI-Skeletons%2Fdoctrine-graphql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAPI-Skeletons%2Fdoctrine-graphql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAPI-Skeletons%2Fdoctrine-graphql/lists"}