diff --git a/CHANGELOG.md b/CHANGELOG.md index cc1177c0..8476afab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ CHANGELOG [Next release](https://github.com/rebing/graphql-laravel/compare/6.2.0...master) -------------- +### Added +- Support for class based schemas [\#706 / jasonvarga](https://github.com/rebing/graphql-laravel/pull/706) + 2021-03-12, 6.2.0 ----------------- ### Fixed diff --git a/README.md b/README.md index 5df2ff5e..c9aa9df3 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,39 @@ in addition to the global middleware. For example: ], ``` +#### Schema classes + +You may alternatively define the configuration of a schema in a class that implements `ConfigConvertible`. + +In your config, you can reference the name of the class, rather than an array. + +```php +'schemas' => [ + 'default' => DefaultSchema::class +] +``` + +```php +namespace App\GraphQL\Schemas; + +use Rebing\GraphQL\Support\Contracts\ConfigConvertible; + +class DefaultSchema implements ConfigConvertible +{ + public function toConfig(): array + { + return [ + 'query' => [ + ExampleQuery::class, + ], + 'mutation' => [ + ExampleMutation::class, + ] + ] + } +} +``` + ### Creating a query First you need to create a type. The Eloquent Model is only required, if specifying relations. diff --git a/src/GraphQL.php b/src/GraphQL.php index 4f66dd17..b7abde06 100644 --- a/src/GraphQL.php +++ b/src/GraphQL.php @@ -21,6 +21,7 @@ use Rebing\GraphQL\Error\ValidationError; use Rebing\GraphQL\Exception\SchemaNotFound; use Rebing\GraphQL\Exception\TypeNotFound; +use Rebing\GraphQL\Support\Contracts\ConfigConvertible; use Rebing\GraphQL\Support\Contracts\TypeConvertible; use Rebing\GraphQL\Support\PaginationType; @@ -31,7 +32,7 @@ class GraphQL /** @var Container */ protected $app; - /** @var array */ + /** @var array */ protected $schemas = []; /** @@ -507,6 +508,15 @@ protected function getSchemaConfiguration($schema) throw new SchemaNotFound('Type '.$schemaName.' not found.'); } - return is_array($schema) ? $schema : $this->schemas[$schemaName]; + $schema = is_array($schema) ? $schema : $this->schemas[$schemaName]; + + if (! is_string($schema)) { + return $schema; + } + + /** @var ConfigConvertible $instance */ + $instance = app()->make($schema); + + return $instance->toConfig(); } } diff --git a/src/Support/Contracts/ConfigConvertible.php b/src/Support/Contracts/ConfigConvertible.php new file mode 100644 index 00000000..bcf593e7 --- /dev/null +++ b/src/Support/Contracts/ConfigConvertible.php @@ -0,0 +1,13 @@ + + */ + public function toConfig(): array; +} diff --git a/tests/Support/Objects/ExampleSchema.php b/tests/Support/Objects/ExampleSchema.php new file mode 100644 index 00000000..cb9c9082 --- /dev/null +++ b/tests/Support/Objects/ExampleSchema.php @@ -0,0 +1,22 @@ + [ + 'examplesCustom' => ExamplesQuery::class, + ], + 'mutation' => [ + 'updateExampleCustom' => UpdateExampleMutation::class, + ], + ]; + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 4ad1318b..45fbf205 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -17,6 +17,7 @@ use Rebing\GraphQL\Tests\Support\Objects\ExampleFilterInputType; use Rebing\GraphQL\Tests\Support\Objects\ExamplesAuthorizeMessageQuery; use Rebing\GraphQL\Tests\Support\Objects\ExamplesAuthorizeQuery; +use Rebing\GraphQL\Tests\Support\Objects\ExampleSchema; use Rebing\GraphQL\Tests\Support\Objects\ExamplesConfigAliasQuery; use Rebing\GraphQL\Tests\Support\Objects\ExamplesFilteredQuery; use Rebing\GraphQL\Tests\Support\Objects\ExamplesMiddlewareQuery; @@ -73,6 +74,9 @@ protected function getEnvironmentSetUp($app) ], ]); + $app['config']->set('graphql.schemas.class_based', ExampleSchema::class); + $app['config']->set('graphql.schemas.invalid_class_based', 'ThisClassDoesntExist'); + $app['config']->set('graphql.types', [ 'Example' => ExampleType::class, 'ExampleConfigAlias' => ExampleType2::class, diff --git a/tests/Unit/GraphQLTest.php b/tests/Unit/GraphQLTest.php index 79b851db..86a15f8a 100644 --- a/tests/Unit/GraphQLTest.php +++ b/tests/Unit/GraphQLTest.php @@ -10,6 +10,7 @@ use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use GraphQL\Type\Schema; +use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Support\Traits\Macroable; use Rebing\GraphQL\Error\ValidationError; use Rebing\GraphQL\Exception\SchemaNotFound; @@ -69,6 +70,19 @@ public function testSchemaWithName(): void $this->assertArrayHasKey('Example', $schema->getTypeMap()); } + /** + * Test schema with name referencing a class. + */ + public function testSchemaWithNameReferencingClass(): void + { + $schema = GraphQL::schema('class_based'); + + $this->assertGraphQLSchema($schema); + $this->assertGraphQLSchemaHasQuery($schema, 'examplesCustom'); + $this->assertGraphQLSchemaHasMutation($schema, 'updateExampleCustom'); + $this->assertArrayHasKey('Example', $schema->getTypeMap()); + } + /** * Test schema custom. */ @@ -101,6 +115,16 @@ public function testSchemaWithWrongName(): void GraphQL::schema('wrong'); } + /** + * Test schema with invalid class name. + */ + public function testSchemaWithInvalidClassName(): void + { + $this->expectException(BindingResolutionException::class); + $this->expectExceptionMessage('Target class [ThisClassDoesntExist] does not exist.'); + GraphQL::schema('invalid_class_based'); + } + /** * Test type. */