diff --git a/CHANGELOG.md b/CHANGELOG.md index b1b4f7ad4..e04c11361 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ You can find and compare releases at the [GitHub release page](https://github.co ## Unreleased +## v15.6.1 + +### Fixed + +- Allow lazy root type callables to return `null` https://github.com/webonyx/graphql-php/pull/1422 + ## v15.6.0 ### Added diff --git a/docs/class-reference.md b/docs/class-reference.md index f37457bd6..1577d3c35 100644 --- a/docs/class-reference.md +++ b/docs/class-reference.md @@ -535,7 +535,7 @@ Usage example: @see Type, NamedType -@phpstan-type MaybeLazyObjectType ObjectType|(callable(): ObjectType)|null +@phpstan-type MaybeLazyObjectType ObjectType|(callable(): (ObjectType|null))|null @phpstan-type TypeLoader callable(string $typeName): ((Type&NamedType)|null) @phpstan-type Types iterable|(callable(): iterable) @phpstan-type SchemaConfigOptions array{ diff --git a/docs/schema-definition.md b/docs/schema-definition.md index a5e3218fe..2ac66bdbf 100644 --- a/docs/schema-definition.md +++ b/docs/schema-definition.md @@ -78,14 +78,14 @@ with complex input values (see [Mutations and Input Types](type-definitions/inpu The schema constructor expects an instance of [`GraphQL\Type\SchemaConfig`](class-reference.md#graphqltypeschemaconfig) or an array with the following options: -| Option | Type | Notes | -| ------------ | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| query | `ObjectType` or `callable(): ObjectType` or `null` | **Required.** Object type (usually named `Query`) containing root-level fields of your read API | -| mutation | `ObjectType` or `callable(): ObjectType` or `null` | Object type (usually named `Mutation`) containing root-level fields of your write API | -| subscription | `ObjectType` or `callable(): ObjectType` or `null` | Reserved for future subscriptions implementation. Currently presented for compatibility with introspection query of **graphql-js**, used by various clients (like Relay or GraphiQL) | -| directives | `array` | A full list of [directives](type-definitions/directives.md) supported by your schema. By default, contains built-in **@skip** and **@include** directives.

If you pass your own directives and still want to use built-in directives - add them explicitly. For example:

_array_merge(GraphQL::getStandardDirectives(), [$myCustomDirective]);_ | -| types | `array` | List of object types which cannot be detected by **graphql-php** during static schema analysis.

Most often this happens when the object type is never referenced in fields directly but is still a part of a schema because it implements an interface which resolves to this object type in its **resolveType** callable.

Note that you are not required to pass all of your types here - it is simply a workaround for a concrete use-case. | -| typeLoader | `callable(string $name): Type` | Expected to return a type instance given the name. Must always return the same instance if called multiple times, see [lazy loading](#lazy-loading-of-types). See section below on lazy type loading. | +| Option | Type | Notes | +| ------------ | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| query | `ObjectType` or `callable(): ?ObjectType` or `null` | **Required.** Object type (usually named `Query`) containing root-level fields of your read API | +| mutation | `ObjectType` or `callable(): ?ObjectType` or `null` | Object type (usually named `Mutation`) containing root-level fields of your write API | +| subscription | `ObjectType` or `callable(): ?ObjectType` or `null` | Reserved for future subscriptions implementation. Currently presented for compatibility with introspection query of **graphql-js**, used by various clients (like Relay or GraphiQL) | +| directives | `array` | A full list of [directives](type-definitions/directives.md) supported by your schema. By default, contains built-in **@skip** and **@include** directives.

If you pass your own directives and still want to use built-in directives - add them explicitly. For example:

_array_merge(GraphQL::getStandardDirectives(), [$myCustomDirective]);_ | +| types | `array` | List of object types which cannot be detected by **graphql-php** during static schema analysis.

Most often this happens when the object type is never referenced in fields directly but is still a part of a schema because it implements an interface which resolves to this object type in its **resolveType** callable.

Note that you are not required to pass all of your types here - it is simply a workaround for a concrete use-case. | +| typeLoader | `callable(string $name): Type` | Expected to return a type instance given the name. Must always return the same instance if called multiple times, see [lazy loading](#lazy-loading-of-types). See section below on lazy type loading. | ### Using config class diff --git a/src/Type/SchemaConfig.php b/src/Type/SchemaConfig.php index b477ed54f..e533a048e 100644 --- a/src/Type/SchemaConfig.php +++ b/src/Type/SchemaConfig.php @@ -26,7 +26,7 @@ * * @see Type, NamedType * - * @phpstan-type MaybeLazyObjectType ObjectType|(callable(): ObjectType)|null + * @phpstan-type MaybeLazyObjectType ObjectType|(callable(): (ObjectType|null))|null * @phpstan-type TypeLoader callable(string $typeName): ((Type&NamedType)|null) * @phpstan-type Types iterable|(callable(): iterable) * @phpstan-type SchemaConfigOptions array{ diff --git a/tests/Type/LazyDefinitionTest.php b/tests/Type/LazyDefinitionTest.php index a378dcdaf..f2efa1367 100644 --- a/tests/Type/LazyDefinitionTest.php +++ b/tests/Type/LazyDefinitionTest.php @@ -208,4 +208,17 @@ public function testLazyRootTypes(): void self::assertSame($schema->getMutationType(), $mutation); self::assertSame($schema->getSubscriptionType(), $subscription); } + + public function testLazyRootTypesNull(): void + { + $schema = new Schema([ + 'query' => fn () => null, + 'mutation' => fn () => null, + 'subscription' => fn () => null, + ]); + + self::assertNull($schema->getQueryType()); + self::assertNull($schema->getMutationType()); + self::assertNull($schema->getSubscriptionType()); + } }