## File: README.md

# graphql-php

**This repository is planned to move to a new home.**
**See the [announcement](https://github.com/webonyx/graphql-php/discussions/1912) for details and to share feedback.**

This is a PHP implementation of the [GraphQL](https://graphql.org) [specification](https://github.com/graphql/graphql-spec)
based on the [reference implementation in JavaScript](https://github.com/graphql/graphql-js).

Fully compliant with the [October 2021 GraphQL specification](https://spec.graphql.org/October2021).
[September 2025 specification](https://spec.graphql.org/September2025) compliance is [in progress](https://github.com/webonyx/graphql-php/issues/1931).

## Sponsors

If you make money using this project, please consider sponsoring [its maintainer on GitHub Sponsors](https://github.com/sponsors/spawnia) or [the project on OpenCollective](https://opencollective.com/webonyx-graphql-php).

[](https://opencollective.com/webonyx-graphql-php/sponsor/0/website)
[](https://opencollective.com/webonyx-graphql-php/sponsor/1/website)
[](https://opencollective.com/webonyx-graphql-php/sponsor/2/website)
[](https://opencollective.com/webonyx-graphql-php/sponsor/3/website)
[](https://opencollective.com/webonyx-graphql-php/sponsor/4/website)
[](https://opencollective.com/webonyx-graphql-php/sponsor/5/website)
[](https://opencollective.com/webonyx-graphql-php/sponsor/6/website)
[](https://opencollective.com/webonyx-graphql-php/sponsor/7/website)
[](https://opencollective.com/webonyx-graphql-php/sponsor/8/website)
[](https://opencollective.com/webonyx-graphql-php/sponsor/9/website)

[](https://opencollective.com/webonyx-graphql-php#backers)

## Installation

Via composer:

```sh
composer require webonyx/graphql-php
```

## Documentation

Full documentation is available at [https://webonyx.github.io/graphql-php](https://webonyx.github.io/graphql-php)
or in the [docs](docs) directory.

## Examples

There are several ready examples in the [examples](examples) directory,
with a specific README file per example.

## Versioning

This project follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).

Elements that belong to the public API of this package are marked with the `@api` PHPDoc tag.
Constants included in the [class-reference docs](https://webonyx.github.io/graphql-php/class-reference) are also part of the public API.
Those elements are thus guaranteed to be stable within major versions.
All other elements are not part of this backwards compatibility guarantee and may change between minor or patch versions.

The most recent version is actively developed on [`master`](https://github.com/webonyx/graphql-php/tree/master).
Older versions are generally no longer supported, although exceptions may be made for [sponsors](#sponsors).

---

## File: docs/type-definitions/directives.md

## Built-in directives

The directive is a way for a client to give GraphQL server additional context and hints on how to execute
the query. The directive can be attached to a field or fragment and can affect the execution of the
query in any way the server desires.

The GraphQL specification includes the following built-in directives:

- **@include(if: Boolean)** Only include this field or fragment in the result if the argument is **true**
- **@skip(if: Boolean)** Skip this field or fragment if the argument is **true**
- **@deprecated(reason: String)** Marks a field, argument, input field, or enum value as deprecated with an optional reason
- **@specifiedBy(url: String!)** Links a custom scalar type to a human-readable specification URL
- **@oneOf** Marks an input object type as a "oneof" input, requiring exactly one field to be non-null

For example:

```graphql
query Hero($episode: Episode, $withFriends: Boolean!) {
  hero(episode: $episode) {
    name
    friends @include(if: $withFriends) {
      name
    }
  }
}
```

Here if **$withFriends** variable is set to **false** - friends section will be ignored and excluded
from the response. Important implementation detail: those fields will never be executed
(not just removed from response after execution).

## Custom directives

**graphql-php** supports custom directives even though their presence does not affect the execution of fields.
You can use [`GraphQL\Type\Definition\ResolveInfo`](../class-reference.md#graphqltypedefinitionresolveinfo)
in field resolvers to modify the output depending on those directives or perform statistics collection.

Other use case is your own query validation rules relying on custom directives.

In **graphql-php** custom directive is an instance of `GraphQL\Type\Definition\Directive`
(or one of its subclasses) which accepts an array of following options:

```php
use GraphQL\Language\DirectiveLocation;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\Directive;

$trackDirective = new Directive([
    'name' => 'track',
    'description' => 'Instruction to record usage of the field by client',
    'locations' => [
        DirectiveLocation::FIELD,
    ],
    'args' => [
        'details' => [
            'type' => Type::string(),
            'description' => 'String with additional details of field usage scenario',
            'defaultValue' => ''
        ]
    ]
]);
```

See possible directive locations in
[`GraphQL\Language\DirectiveLocation`](../class-reference.md#graphqllanguagedirectivelocation).

---

## File: docs/type-definitions/enums.md

# Enum Type Definition

Enumeration types are a special kind of scalar that is restricted to a particular set
of allowed values.

## Writing Enum Types

In **graphql-php** enum type is an instance of `GraphQL\Type\Definition\EnumType`
which accepts configuration array in constructor:

```php
use GraphQL\Type\Definition\EnumType;

$episodeEnum = new EnumType([
    'name' => 'Episode',
    'description' => 'One of the films in the Star Wars Trilogy',
    'values' => [
        'NEWHOPE' => [
            'value' => 4,
            'description' => 'Released in 1977.'
        ],
        'EMPIRE' => [
            'value' => 5,
            'description' => 'Released in 1980.'
        ],
        'JEDI' => [
            'value' => 6,
            'description' => 'Released in 1983.'
        ],
    ]
]);
```

This example uses an **inline** style for Enum Type definition, but you can also use
[inheritance or schema definition language](index.md#definition-styles).

## Configuration options

Enum Type constructor accepts an array with following options:

| Option      | Type     | Notes                                                                                                                                          |
| ----------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| name        | `string` | **Required.** Name of the type. When not set - inferred from array key (read about [shorthand field definition](#shorthand-definitions) below) |
| description | `string` | Plain-text description of the type for clients (e.g. used by [GraphiQL](https://github.com/graphql/graphiql) for auto-generated documentation) |
| values      | `array`  | List of enumerated items, see below for expected structure of each entry                                                                       |

Each entry of **values** array in turn accepts following options:

| Option            | Type     | Notes                                                                                                                                            |
| ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| name              | `string` | **Required.** Name of the item. When not set - inferred from array key (read about [shorthand field definition](#shorthand-definitions) below)   |
| value             | `mixed`  | Internal representation of enum item in your application (could be any value, including complex objects or callbacks)                            |
| description       | `string` | Plain-text description of enum value for clients (e.g. used by [GraphiQL](https://github.com/graphql/graphiql) for auto-generated documentation) |
| deprecationReason | `string` | Text describing why this enum value is deprecated. When not empty - item will not be returned by introspection queries (unless forced)           |

## Construction from PHP enum

You can reuse your existing PHP enums in GraphQL.
Leverage PHP attributes to add descriptions and deprecate values:

```php
use GraphQL\Type\Definition\Deprecated;
use GraphQL\Type\Definition\Description;

#[Description(description: 'Sweet and juicy.')]
enum Fruit
{
    #[Description(description: 'Rich in potassium.')]
    case BANANA;

    #[Deprecated(reason: 'Too sour.')]
    case CITRON;
}
```

PhpDocs will be used as descriptions if present, but are overridden by the `Description` attribute.

Wrap them with `GraphQL\Type\Definition\PhpEnumType` to use them in a GraphQL schema:

```php
use GraphQL\Type\Definition\PhpEnumType;

$fruitEnumType = new PhpEnumType(Fruit::class);
```

The following type will be deduced from `Fruit`:

```graphql
"""
Sweet and juicy.
"""
enum Fruit {
  """
  Rich in potassium.
  """
  BANANA

  CITRON @deprecated(reason: "Too sour.")
}
```

Conversion rules:

- Client-given arguments will be converted to enum instances
- Returned output values are expected to be enum instances

## Shorthand definitions

If internal representation of enumerated item is the same as item name, then you can use
following shorthand for definition:

```php
use GraphQL\Type\Definition\EnumType;

$episodeEnum = new EnumType([
    'name' => 'Episode',
    'description' => 'One of the films in the Star Wars Trilogy',
    'values' => ['NEWHOPE', 'EMPIRE', 'JEDI']
]);
```

which is equivalent of:

```php
use GraphQL\Type\Definition\EnumType;

$episodeEnum = new EnumType([
    'name' => 'Episode',
    'description' => 'One of the films in the Star Wars Trilogy',
    'values' => [
        'NEWHOPE' => ['value' => 'NEWHOPE'],
        'EMPIRE' => ['value' => 'EMPIRE'],
        'JEDI' => ['value' => 'JEDI']
    ]
]);
```

which is in turn equivalent of the full form:

```php
use GraphQL\Type\Definition\EnumType;

$episodeEnum = new EnumType([
    'name' => 'Episode',
    'description' => 'One of the films in the Star Wars Trilogy',
    'values' => [
        ['name' => 'NEWHOPE', 'value' => 'NEWHOPE'],
        ['name' => 'EMPIRE', 'value' => 'EMPIRE'],
        ['name' => 'JEDI', 'value' => 'JEDI']
    ]
]);
```

## Field Resolution

When object field is of Enum Type, field resolver is expected to return an internal
representation of corresponding Enum item (**value** in config). **graphql-php** will
then serialize this **value** to **name** to include in response:

```php
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\ObjectType;

$episodeEnum = new EnumType([
    'name' => 'Episode',
    'description' => 'One of the films in the Star Wars Trilogy',
    'values' => [
        'NEWHOPE' => [
            'value' => 4,
            'description' => 'Released in 1977.'
        ],
        'EMPIRE' => [
            'value' => 5,
            'description' => 'Released in 1980.'
        ],
        'JEDI' => [
            'value' => 6,
            'description' => 'Released in 1983.'
        ],
    ]
]);

$heroType = new ObjectType([
    'name' => 'Hero',
    'fields' => [
        'appearsIn' => [
            'type' => $episodeEnum,
             // Actual entry in response will be 'appearsIn' => 'EMPIRE'
            'resolve' => fn (): int => 5,
        ]
    ]
]);
```

The Reverse is true when the enum is used as input type (e.g. as field argument).
GraphQL will treat enum input as **name** and convert it into **value** before passing to your app.

For example, given object type definition:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$heroType = new ObjectType([
    'name' => 'Hero',
    'fields' => [
        'appearsIn' => [
            'type' => Type::boolean(),
            'args' => [
                'episode' => Type::nonNull($enumType)
            ],
            'resolve' => fn ($hero, array $args): bool => $args['episode'] === 5,
        ]
    ]
]);
```

Then following query:

```graphql
fragment on Hero {
    appearsInNewHope: appearsIn(NEWHOPE)
    appearsInEmpire: appearsIn(EMPIRE)
}
```

will return:

```php
[
    'appearsInNewHope' => false,
    'appearsInEmpire' => true
]
```

---

## File: docs/type-definitions/index.md

# Type Definitions

graphql-php represents a **type** as a class instance from the `GraphQL\Type\Definition` namespace:

- [`ObjectType`](object-types.md)
- [`InterfaceType`](interfaces.md)
- [`UnionType`](unions.md)
- [`InputObjectType`](inputs.md)
- [`ScalarType`](scalars.md)
- [`EnumType`](enums.md)

## Input vs. Output Types

All types in GraphQL are of two categories: **input** and **output**.

- **Output** types (or field types) are: [Scalar](scalars.md), [Enum](enums.md), [Object](object-types.md),
  [Interface](interfaces.md), [Union](unions.md)

- **Input** types (or argument types) are: [Scalar](scalars.md), [Enum](enums.md), [Inputs](inputs.md)

Obviously, [NonNull and List](lists-and-nonnulls.md) types belong to both categories depending on their
inner type.

## Definition styles

Several styles of type definitions are supported depending on your preferences.

### Inline definitions

```php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

$myType = new ObjectType([
    'name' => 'MyType',
    'fields' => [
        'id' => Type::id()
    ]
]);
```

### Class per type

```php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

class MyType extends ObjectType
{
    public function __construct()
    {
        $config = [
            // Note: 'name' is not needed in this form:
            // it will be inferred from class name by omitting namespace and dropping "Type" suffix
            'fields' => [
                'id' => Type::id()
            ]
        ];
        parent::__construct($config);
    }
}
```

### Schema definition language

```graphql
schema {
  query: Query
  mutation: Mutation
}

type Query {
  greetings(input: HelloInput!): String!
}

input HelloInput {
  firstName: String!
  lastName: String
}
```

Read more about [building an executable schema using schema definition language](../schema-definition-language.md).

---

## File: docs/type-definitions/inputs.md

# Input Object Type Definition

The GraphQL specification defines the Input Object type for complex inputs.
It is similar to the Object type, but its fields have no **args** or **resolve** options and their **type** must be input type.

## Writing Input Object Types

In graphql-php, **Input Object Type** is an instance of `GraphQL\Type\Definition\InputObjectType`
(or one of its subclasses) which accepts configuration array in its constructor:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\InputObjectType;

$filters = new InputObjectType([
    'name' => 'StoryFiltersInput',
    'fields' => [
        'author' => [
            'type' => Type::id(),
            'description' => 'Only show stories with this author id'
        ],
        'popular' => [
            'type' => Type::boolean(),
            'description' => 'Only show popular stories (liked by several people)'
        ],
        'tags' => [
            'type' => Type::listOf(Type::string()),
            'description' => 'Only show stories which contain all of those tags'
        ]
    ]
]);
```

Every field may be of other InputObjectType (thus complex hierarchies of inputs are possible)

## Configuration options

The constructor of `InputObjectType` accepts an `array` with the following options:

| Option      | Type                                                           | Notes                                                                                                                                           |
| ----------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name        | `string`                                                       | **Required.** Unique name of this object type within Schema                                                                                     |
| description | `string`                                                       | Plain-text description of this type for clients (e.g. used by [GraphiQL](https://github.com/graphql/graphiql) for auto-generated documentation) |
| isOneOf     | `bool`                                                         | Indicates that an Input Object is a OneOf Input Object (and thus requires exactly one of its fields be provided).                               |
| parseValue  | `callable(array<string, mixed>): mixed`                        | Converts incoming values from their array representation to something else (e.g. a value object)                                                |
| fields      | `iterable<FieldConfig>` or `callable(): iterable<FieldConfig>` | **Required**. An iterable describing object fields or callable returning such an iterable (see below).                                          |

Every entry in `fields` is an array with following entries:

| Option            | Type     | Notes                                                                                                                                                                      |
| ----------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name              | `string` | **Required.** Name of the input field. When not set - inferred from **fields** array key                                                                                   |
| type              | `Type`   | **Required.** Instance of one of [Input Types](inputs.md) (**Scalar**, **Enum**, **InputObjectType** + any combination of those with **nonNull** and **listOf** modifiers) |
| defaultValue      | `scalar` | Default value of this input field. Use the internal value if specifying a default for an **enum** type                                                                     |
| description       | `string` | Plain-text description of this input field for clients (e.g. used by [GraphiQL](https://github.com/graphql/graphiql) for auto-generated documentation)                     |
| deprecationReason | `string` | Plain-test reason for why this input field is deprecated.                                                                                                                  |

## Using Input Object Type

In the example above we defined our InputObjectType `StoryFiltersInput`.
Now let's use it in one of field arguments:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$queryType = new ObjectType([
    'name' => 'Query',
    'fields' => [
        'stories' => [
            'type' => Type::listOf($storyType),
            'args' => [
                'filters' => [
                    'type' => $filters,
                    'defaultValue' => [
                        'popular' => true,
                    ],
                ],
            ],
            'resolve' => fn ($rootValue, array $args): array => DataSource::filterStories($args['filters']),
        ],
    ],
]);
```

You can define **defaultValue** for fields with complex inputs as an associative array.

Then GraphQL query could include filters as a literal value:

```graphql
{
  stories(filters: {
    author: "1"
    popular: false
  }) {
    ...
  }
}
```

Or as a query variable:

```graphql
query ($filters: StoryFiltersInput!) {
  stories(filters: $filters) {
    ...
  }
}
```

```json
{
  "filters": {
    "author": "1",
    "popular": false
  }
}
```

**graphql-php** will validate the input against your InputObjectType definition and pass it to your resolver as `$args['filters']`.

## Converting Input Array to Value Object

If you want more type safety you can choose to parse the input array into a value object.

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\InputObjectType;

final readonly class StoryFiltersInput
{
    public function __construct(
        public string $author,
        public ?bool $popular,
        /** @var array<string> */
        public array $tags
    ) {}
}

$filters = new InputObjectType([
    'name' => 'StoryFiltersInput',
    'fields' => [
        'author' => [
            'type' => Type::nonNull(Type::string()),
        ],
        'popular' => [
            'type' => Type::boolean(),
        ],
        'tags' => [
            'type' => Type::nonNull(Type::listOf(Type::string())),
        ]
    ],
    'parseValue' => fn (array $values): StoryFiltersInput => new StoryFiltersInput(
        author: $values['author'],
        popular: $values['popular'] ?? null,
        tags: $values['tags'],
    ),
]);
```

The value of `$args['filters']` will now be an instance of `StoryFiltersInput`.

The incoming values are converted using a depth-first traversal.
Thus, nested input values will be passed through their respective `parseValue` functions before the parent receives their value.

## Using the `isOneOf` Configuration Option

The `isOneOf` configuration option allows you to declare an input object as a _OneOf Input Object_.
This means that exactly one of its fields must be provided when the input is used.
This is useful when an argument can accept several alternative values, but never more than one at the same time.

Suppose you want to allow a query to filter stories either by author **or** by tag, but not both together.
You can define an input object with `isOneOf: true`:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\InputObjectType;

$storySearch = new InputObjectType([
    'name' => 'StorySearchInput',
    'isOneOf' => true,
    'fields' => [
        'author' => [
            'type' => Type::id(),
            'description' => 'Find stories by a specific author',
        ],
        'tag' => [
            'type' => Type::string(),
            'description' => 'Find stories with a specific tag',
        ],
    ],
]);
```

This input object can then be used as an argument in a query:

```php
$searchType = new ObjectType([
    'name' => 'Query',
    'fields' => [
        'searchStories' => [
            'type' => Type::listOf($storyType),
            'args' => [
                'search' => [
                    'type' => $storySearch,
                ],
            ],
            'resolve' => fn ($rootValue, array $args): array => DataSource::searchStories($args['search']),
        ],
    ],
]);
```

```graphql
{
  searchStories(search: { author: "1" }) {
    id
    title
  }
}
```

If you try to provide both fields at once, validation will fail:

```graphql
{
  searchStories(search: { author: "1", tag: "php" }) {
    id
    title
  }
}
```

**graphql-php** ensures that with `isOneOf: true`, exactly one field is set.
This helps make APIs clearer and less error-prone when alternative inputs are required.

---

## File: docs/type-definitions/interfaces.md

# Interface Type Definition

An Interface is an abstract type that includes a certain set of fields that a
type must include to implement the interface.

## Writing Interface Types

In **graphql-php** interface type is an instance of `GraphQL\Type\Definition\InterfaceType`
(or one of its subclasses) which accepts configuration array in a constructor:

```php
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

$character = new InterfaceType([
    'name' => 'Character',
    'description' => 'A character in the Star Wars Trilogy',
    'fields' => [
        'id' => [
            'type' => Type::nonNull(Type::string()),
            'description' => 'The id of the character.',
        ],
        'name' => [
            'type' => Type::string(),
            'description' => 'The name of the character.'
        ]
    ],
    'resolveType' => function ($value): ObjectType {
        switch ($value->type ?? null) {
            case 'human': return MyTypes::human();
            case 'droid': return MyTypes::droid();
            default: throw new Exception("Unknown Character type: {$value->type ?? null}");
        }
    }
]);
```

This example uses **inline** style for Interface definition, but you can also use  
[inheritance or schema definition language](index.md#definition-styles).

## Configuration options

The constructor of InterfaceType accepts an array. Below is a full list of allowed options:

| Option      | Type       | Notes                                                                                                                                                                                                                                  |
| ----------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name        | `string`   | **Required.** Unique name of this interface type within Schema                                                                                                                                                                         |
| fields      | `array`    | **Required.** List of fields required to be defined by interface implementors. Same as [Fields for Object Type](object-types.md#field-configuration-options)                                                                           |
| description | `string`   | Plain-text description of this type for clients (e.g. used by [GraphiQL](https://github.com/graphql/graphiql) for auto-generated documentation)                                                                                        |
| resolveType | `callback` | **function ($value, $context, [ResolveInfo](../class-reference.md#graphqltypedefinitionresolveinfo) $info)** Receives **$value** from resolver of the parent field and returns concrete interface implementor for this **$value**. |

## Implementing interface

To implement the Interface simply add it to **interfaces** array of Object Type definition:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$humanType = new ObjectType([
    'name' => 'Human',
    'fields' => [
        'id' => [
            'type' => Type::nonNull(Type::string()),
            'description' => 'The id of the character.',
        ],
        'name' => [
            'type' => Type::string(),
            'description' => 'The name of the character.'
        ]
    ],
    'interfaces' => [
        $character
    ]
]);
```

Note that Object Type must include all fields of interface with exact same types
(including **nonNull** specification) and arguments.

The only exception is when object's field type is more specific than the type of this field defined in interface
(see [Covariant return types for interface fields](#covariant-return-types-for-interface-fields) below)

## Covariant return types for interface fields

Object types implementing interface may change the field type to more specific.
Example:

```graphql
interface A {
  field1: A
}

type B implements A {
  field1: B
}
```

## Sharing Interface fields

Since every Object Type implementing an Interface must have the same set of fields - it often makes
sense to reuse field definitions of Interface in Object Types:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$humanType = new ObjectType([
    'name' => 'Human',
    'interfaces' => [
        $character
    ],
    'fields' => [
        $character->getField('id'),
        $character->getField('name'),
        [
            'name' => 'height',
            'type' => Type::float(),
        ],
    ]
]);
```

In this case, field definitions are created only once (as a part of the Interface Type) and then reused by all interface implementors.
It can save several microseconds and kilobytes and ensures that field definitions of Interface and implementors are always in sync.
Yet it creates a problem with the resolution of such fields.

There are two ways how shared fields could be resolved:

1. If the field resolution algorithm is the same for all Interface implementors,
   you can add the **resolve** option to the field definition in the Interface itself.

2. If field resolution varies for different implementations, you can specify the **resolveField** option
   in [the Object Type config](object-types.md#configuration-options) and handle field resolutions there.
   (Note: The **resolve** option in field definitions has precedence over the **resolveField** option in object type definitions.)

## Interface role in data fetching

The only responsibility of interface in Data Fetching process is to return concrete Object Type
for given **$value** in **resolveType**. Then resolution of fields is delegated to resolvers of this
concrete Object Type.

If a **resolveType** option is omitted, graphql-php will loop through all interface implementors and
use their **isTypeOf** callback to pick the first suitable one. This is obviously less efficient
than single **resolveType** call. So it is recommended to define **resolveType** whenever possible.

## Prevent invisible types

When object types that implement an interface are not directly referenced by a field, they cannot
be discovered during schema introspection. For example:

```graphql
type Query {
    animal: Animal
}

interface Animal {...}

type Cat implements Animal {...}
type Dog implements Animal {...}
```

In this example, `Cat` and `Dog` would be considered _invisible_ types. Querying the `animal` field
would fail, since no possible implementing types for `Animal` can be found.

There are two possible solutions:

1. Add fields that reference the invisible types directly, e.g.:

   ```graphql
   type Query {
     dog: Dog
     cat: Cat
   }
   ```

2. Pass the invisible types during schema construction, e.g.:

```php
new GraphQLSchema([
    'query' => ...,
    'types' => [$cat, $dog]
]);
```

---

## File: docs/type-definitions/lists-and-nonnulls.md

## Lists

**graphql-php** provides built-in support for lists. In order to create list type - wrap
existing type with `GraphQL\Type\Definition\Type::listOf()` modifier:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$userType = new ObjectType([
    'name' => 'User',
    'fields' => [
        'emails' => [
            'type' => Type::listOf(Type::string()),
            'resolve' => fn (): array => [
                'jon@example.com',
                'jonny@example.com'
            ],
        ]
    ]
]);
```

Resolvers for such fields are expected to return **array** or instance of PHP's built-in **Traversable**
interface (**null** is allowed by default too).

If returned value is not of one of these types - **graphql-php** will add an error to result
and set the field value to **null** (only if the field is nullable, see below for non-null fields).

## Non-Nulls

By default, every field or argument can have a **null** value.
To indicate the value must be **non-null** use the `GraphQL\Type\Definition\Type::nonNull()` modifier:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$humanType = new ObjectType([
    'name' => 'User',
    'fields' => [
        'id' => [
            'type' => Type::nonNull(Type::id()),
            'resolve' => fn (): string => uniqid(),
        ],
        'emails' => [
            'type' => Type::nonNull(Type::listOf(Type::string())),
            'resolve' => fn (): array => [
                'jon@example.com',
                'jonny@example.com'
            ],
        ]
    ]
]);
```

If resolver of non-null field returns **null**, graphql-php will add an error to
result and exclude the whole object from the output (an error will bubble to first
nullable parent field which will be set to **null**).

Read the section on [Data Fetching](../data-fetching.md) for details.

---

## File: docs/type-definitions/object-types.md

# Object Type Definition

Object Type is the most frequently used primitive in a typical GraphQL application.

Conceptually Object Type is a collection of Fields. Each field, in turn,
has its own type which allows building complex hierarchies.

## Writing Object Types

In **graphql-php** object type is an instance of `GraphQL\Type\Definition\ObjectType`
(or one of its subclasses) which accepts a configuration array in its constructor:

```php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Examples\Blog\Data\DataSource;
use GraphQL\Examples\Blog\Data\Story;

$userType = new ObjectType([
    'name' => 'User',
    'description' => 'Our blog visitor',
    'fields' => [
        'firstName' => [
            'type' => Type::string(),
            'description' => 'User first name'
        ],
        'email' => Type::string()
    ]
]);

$blogStory = new ObjectType([
    'name' => 'Story',
    'fields' => [
        'body' => Type::string(),
        'author' => [
            'type' => $userType,
            'description' => 'Story author',
            'resolve' => fn (Story $blogStory): ?User => DataSource::findUser($blogStory->authorId),
        ],
        'likes' => [
            'type' => Type::listOf($userType),
            'description' => 'List of users who liked the story',
            'args' => [
                'limit' => [
                    'type' => Type::int(),
                    'description' => 'Limit the number of recent likes returned',
                    'defaultValue' => 10
                ]
            ],
            'resolve' => fn (Story $blogStory, array $args): array => DataSource::findLikes($blogStory->id, $args['limit']),
        ]
    ]
]);
```

This example uses **inline** style for Object Type definitions, but you can also use  
[inheritance or schema definition language](index.md#definition-styles).

## Configuration options

| Option       | Type                  | Notes                                                                                                                                                                                                                                                                                                                                                                           |
| ------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name         | `string`              | **Required.** Unique name of this object type within Schema                                                                                                                                                                                                                                                                                                                     |
| fields       | `array` or `callable` | **Required**. An array describing object fields or callable returning such an array. See [field configuration options](#field-configuration-options) section below for expected structure of each array entry. See also the section on [Circular types](#recurring-and-circular-types) for an explanation of when to use callable for this option.                              |
| description  | `string`              | Plain-text description of this type for clients (e.g. used by [GraphiQL](https://github.com/graphql/graphiql) for auto-generated documentation)                                                                                                                                                                                                                                 |
| interfaces   | `array` or `callable` | List of interfaces implemented by this type or callable returning such a list. See [Interface Types](interfaces.md) for details. See also the section on [Circular types](#recurring-and-circular-types) for an explanation of when to use callable for this option.                                                                                                            |
| isTypeOf     | `callable`            | **function ($value, $context, [ResolveInfo](../class-reference.md#graphqltypedefinitionresolveinfo) $info): bool** Expected to return **true** if **$value** qualifies for this type (see section about [Abstract Type Resolution](interfaces.md#interface-role-in-data-fetching) for explanation).                                                                         |
| resolveField | `callable`            | **function ($value, array $args, $context, [ResolveInfo](../class-reference.md#graphqltypedefinitionresolveinfo) $info): mixed** Given the **$value** of this type, it is expected to return value for a field defined in **$info->fieldName**. A good place to define a type-specific strategy for field resolution. See [Data Fetching](../data-fetching.md) for details. |
| argsMapper   | `callable`            | **function (array $args, FieldDefinition, FieldNode): mixed** Called once, when Executor resolves arguments for given field. Could be used to validate args and/or to map them to DTO/Object.                                                                                                                                                                               |
| visible      | `bool` or `callable`  | Defaults to `true`. The given callable receives no arguments and is expected to return a `bool`, it is called once when the field may be accessed. The field is treated as if it were not defined at all when this is `false`.                                                                                                                                                  |

### Field configuration options

| Option            | Type       | Notes                                                                                                                                                                                                                                                                                                           |
| ----------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name              | `string`   | **Required.** Name of the field. When not set - inferred from **fields** array key (read about [shorthand field definition](#shorthand-field-definitions) below)                                                                                                                                                |
| type              | `Type`     | **Required.** An instance of internal or custom type. Note: type must be represented by a single instance within one schema (see also [lazy loading of types](../schema-definition.md#lazy-loading-of-types))                                                                                                   |
| args              | `array`    | An array describing any number of possible field arguments, each element being an array. See [field argument configuration options](#field-argument-configuration-options).                                                                                                                                     |
| resolve           | `callable` | **function ($objectValue, array $args, $context, [ResolveInfo](../class-reference.md#graphqltypedefinitionresolveinfo) $info): mixed** Given the **$objectValue** of this type, it is expected to return actual value of the current field. See section on [Data Fetching](../data-fetching.md) for details |
| complexity        | `callable` | **function (int $childrenComplexity, array $args): int** Used to restrict query complexity. The feature is disabled by default, read about [Security](../security.md#query-complexity-analysis) to use it.                                                                                                  |
| description       | `string`   | Plain-text description of this field for clients (e.g. used by [GraphiQL](https://github.com/graphql/graphiql) for auto-generated documentation)                                                                                                                                                                |
| deprecationReason | `string`   | Text describing why this field is deprecated. When not empty - field will not be returned by introspection queries (unless forced)                                                                                                                                                                              |

### Field argument configuration options

| Option       | Type     | Notes                                                                                                                                                                      |
| ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name         | `string` | **Required.** Name of the argument. When not set - inferred from **args** array key                                                                                        |
| type         | `Type`   | **Required.** Instance of one of [Input Types](inputs.md) (**scalar**, **enum**, **InputObjectType** + any combination of those with **nonNull** and **listOf** modifiers) |
| description  | `string` | Plain-text description of this argument for clients (e.g. used by [GraphiQL](https://github.com/graphql/graphiql) for auto-generated documentation)                        |
| defaultValue | `scalar` | Default value for this argument. Use the internal value if specifying a default for an **enum** type                                                                       |

## Shorthand field definitions

Fields can be also defined in **shorthand** notation (with only **name** and **type** options):

```php
'fields' => [
    'id' => Type::id(),
    'fieldName' => $fieldType
]
```

which is equivalent of:

```php
'fields' => [
    'id' => ['type' => Type::id()],
    'fieldName' => ['type' => $fieldName]
]
```

which is in turn equivalent of the full form:

```php
'fields' => [
    ['name' => 'id', 'type' => Type::id()],
    ['name' => 'fieldName', 'type' => $fieldName]
]
```

Same shorthand notation applies to field arguments as well.

## Recurring and circular types

Almost all real-world applications contain recurring or circular types.
Think user friends or nested comments for example.

**graphql-php** allows such types, but you have to use `callable` in
option **fields** (and/or **interfaces**).

For example:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$userType = new ObjectType([
    'name' => 'User',
    'fields' => function () use (&$userType): array {
        return [
            'email' => [
                'type' => Type::string()
            ],
            'friends' => [
                'type' => Type::listOf($userType)
            ]
        ];
    },
]);
```

Same example for [inheritance style of type definitions](index.md#definition-styles)
using a type registry (see [lazy loading of types](../schema-definition.md#lazy-loading-of-types)):

```php
use GraphQL\Type\Definition\ListOfType;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

class UserType extends ObjectType
{
    public function __construct()
    {
        parent::__construct([
            'fields' => [
                'email' => fn (): ScalarType => MyTypes::string(),
                'friends' => fn (): ListOfType => MyTypes::listOf(MyTypes::user())
            ],
        ]);
    }
}

class MyTypes
{
    private static UserType $user;

    public static function user(): UserType
    {
        return self::$user ??= new UserType();
    }

    public static function string(): ScalarType
    {
        return Type::string();
    }

    public static function listOf($type): ListOfType
    {
        return Type::listOf($type);
    }
}
```

## Field Resolution

Field resolution is the primary mechanism in **graphql-php** for returning actual data for your fields.
It is implemented using a **resolveField** callable in type definitions,
or a **resolve** callable in field definitions (the latter has precedence).

Read the section on [Data Fetching](../data-fetching.md) for a complete description of this process.

## Custom Metadata

All types in **graphql-php** accept a configuration array.
In some cases, you may be interested in passing your own metadata for type or field definition.

**graphql-php** preserves the original configuration array in every type or field instance in a public property **$config**.
You may use it for custom implementations that are not natively supported by this library.

---

## File: docs/type-definitions/scalars.md

# Scalar Type Definition

Scalar types represent primitive leaf values in a GraphQL type system.
When object fields have to resolve to some concrete data, that's where the scalar types come in.

## Built-in Scalar Types

The GraphQL specification describes several built-in scalar types. In **graphql-php** they are
exposed as static methods of the class [`GraphQL\Type\Definition\Type`](../class-reference.md#graphqltypedefinitiontype):

```php
use GraphQL\Type\Definition\Type;

// Built-in Scalar types:
Type::string();  // String type
Type::int();     // Int type
Type::float();   // Float type
Type::boolean(); // Boolean type
Type::id();      // ID type
```

Those methods return instances of a subclass of `GraphQL\Type\Definition\ScalarType`.
Use them directly in type definitions or wrapped in a type registry (see [lazy loading of types](../schema-definition.md#lazy-loading-of-types)).

## Writing Custom Scalar Types

In addition to built-in scalars, you can define your own scalar types with additional validation.
Typical examples of such types are **Email**, **Date**, **Url**, etc.

In order to implement your own type, you must understand how scalars are handled in GraphQL.
GraphQL deals with scalars in the following cases:

1. Convert the **internal representation** of a value, returned by your app (e.g. stored in a database
   or hardcoded in the source code), to a **serialized representation** included in the response.

2. Convert an **input value**, passed by a client in variables along with a GraphQL query, to
   its **internal representation** used in your application.

3. Convert an **input literal value**, hardcoded in a GraphQL query (e.g. field argument value), to
   its **internal representation** used in your application.

Those cases are covered by the methods `serialize`, `parseValue` and `parseLiteral` of the
abstract class `ScalarType` respectively.

Here is an example of a simple **Email** type:

```php
use GraphQL\Error\Error;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\StringValueNode;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Utils\Utils;

class EmailType extends ScalarType
{
    // Note: name can be omitted. In this case it will be inferred from class name
    // (suffix "Type" will be dropped)
    public string $name = 'Email';

    public function serialize($value)
    {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new InvariantViolation("Could not serialize following value as email: " . Utils::printSafe($value));
        }

        return $this->parseValue($value);
    }

    public function parseValue($value)
    {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new Error("Cannot represent following value as email: " . Utils::printSafeJson($value));
        }

        return $value;
    }

    public function parseLiteral(Node $valueNode, ?array $variables = null)
    {
        // Throw GraphQL\Error\Error vs \UnexpectedValueException to locate the error in the query
        if (!$valueNode instanceof StringValueNode) {
            throw new Error('Query error: Can only parse strings got: ' . $valueNode->kind, [$valueNode]);
        }

        if (!filter_var($valueNode->value, FILTER_VALIDATE_EMAIL)) {
            throw new Error("Not a valid email", [$valueNode]);
        }

        return $valueNode->value;
    }
}
```

Or with inline style:

```php
use GraphQL\Type\Definition\CustomScalarType;

$emailType = new CustomScalarType([
    'name' => 'Email',
    'serialize' => static function ($value) {/* See function body above */},
    'parseValue' => static function ($value) {/* See function body above */},
    'parseLiteral' => static function (Node $valueNode, ?array $variables = null) {/* See function body above */},
]);
```

Keep in mind the passed functions will be called statically, so a passed in `callable`
such as `[Foo::class, 'bar']` should only reference static class methods.

## Linking a Scalar to Its Specification

The `@specifiedBy` built-in directive lets you attach a URL to a custom scalar that specifies the behavior of that scalar.
This URL is exposed through introspection and printed in SDL output.

Pass `specifiedByURL` when constructing the type:

```php
use GraphQL\Type\Definition\CustomScalarType;

$uuidType = new CustomScalarType([
    'name' => 'UUID',
    'specifiedByURL' => 'https://tools.ietf.org/html/rfc4122',
    'serialize' => static function ($value) { /* ... */ },
    'parseValue' => static function ($value) { /* ... */ },
    'parseLiteral' => static function ($valueNode, ?array $variables = null) { /* ... */ },
]);

$uuidType->specifiedByURL; // "https://tools.ietf.org/html/rfc4122"
```

When building a schema from SDL, `@specifiedBy` is parsed automatically:

```graphql
scalar UUID @specifiedBy(url: "https://tools.ietf.org/html/rfc4122")
```

And `SchemaPrinter` will emit the directive when printing a schema that contains a scalar with a `specifiedByURL`.

## Overriding Built-in Scalars

You can override built-in scalars (`String`, `Int`, `Float`, `Boolean`, `ID`) on a per-schema basis by passing a custom scalar with the same name through the `types` option.
This works with or without a `typeLoader`:

```php
use GraphQL\Type\Definition\CustomScalarType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;

$uppercaseString = new CustomScalarType([
    'name' => 'String',
    'serialize' => static fn ($value): string => strtoupper((string) $value),
]);

$schema = new Schema([
    'query' => $queryType,
    'typeLoader' => $myTypeLoader,
    'types' => [$uppercaseString],
]);
```

The custom scalar replaces the built-in one throughout the entire schema, affecting both serialization of results and coercion of inputs.

> **Note:** The `typeLoader` is never called for built-in scalar names.
> Always use `types` or `scalarOverrides` to override them.

Discovering overrides requires scanning `types`.
When `types` is a lazy callable, the scan resolves it on the first lookup of a built-in scalar - typically the first executed query.
To avoid this in schemas that use [lazy loading of types](../schema-definition.md#lazy-loading-of-types), pass overrides explicitly through the `scalarOverrides` option instead - or pass an empty array to declare there are none:

```php
$schema = new Schema([
    'query' => $queryType,
    'typeLoader' => $myTypeLoader,
    'types' => $myLazyTypes,
    'scalarOverrides' => [$uppercaseString], // or [] for none
]);
```

---

## File: docs/type-definitions/unions.md

# Union Type Definition

A Union is an abstract type that simply enumerates other Object Types.
The value of Union Type is actually a value of one of included Object Types.

## Writing Union Types

In **graphql-php** union type is an instance of `GraphQL\Type\Definition\UnionType`
(or one of its subclasses) which accepts configuration array in a constructor:

```php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\UnionType;

$searchResultType = new UnionType([
    'name' => 'SearchResult',
    'types' => [
        MyTypes::story(),
        MyTypes::user()
    ],
    'resolveType' => function ($value): ObjectType {
        switch ($value->type ?? null) {
            case 'story': return MyTypes::story();
            case 'user': return MyTypes::user();
            default: throw new Exception("Unexpected SearchResult type: {$value->type ?? null}");
        }
    },
]);
```

This example uses **inline** style for Union definition, but you can also use  
[inheritance or schema definition language](index.md#definition-styles).

## Configuration options

The constructor of UnionType accepts an array. Below is a full list of allowed options:

| Option      | Type       | Notes                                                                                                                                                                                                                                    |
| ----------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name        | `string`   | **Required.** Unique name of this interface type within Schema                                                                                                                                                                           |
| types       | `array`    | **Required.** List of Object Types included in this Union. Note that you can't create a Union type out of Interfaces or other Unions.                                                                                                    |
| description | `string`   | Plain-text description of this type for clients (e.g. used by [GraphiQL](https://github.com/graphql/graphiql) for auto-generated documentation)                                                                                          |
| resolveType | `callback` | **function ($value, $context, [ResolveInfo](../class-reference.md#graphqltypedefinitionresolveinfo) $info): ObjectType** Receives **$value** from resolver of the parent field and returns concrete Object Type for this **$value**. |