PHPackages                             wwwision/types-graphql - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. wwwision/types-graphql

ActiveLibrary

wwwision/types-graphql
======================

1.4.0(9mo ago)08.6k↓19.7%12MITPHPPHP &gt;=8.1CI passing

Since Jul 31Pushed 9mo ago1 watchersCompare

[ Source](https://github.com/bwaidelich/types-graphql)[ Packagist](https://packagist.org/packages/wwwision/types-graphql)[ GitHub Sponsors](https://github.com/sponsors/bwaidelich)[ Fund](https://www.paypal.me/bwaidelich)[ RSS](/packages/wwwision-types-graphql/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (8)Dependencies (6)Versions (9)Used By (2)

types-graphql
=============

[](#types-graphql)

Integration for the [wwwision/types](https://github.com/bwaidelich/types) package that allows to generate GraphQL schemas from PHP code

Usage
-----

[](#usage)

This package can be installed via [composer](https://getcomposer.org):

```
composer require wwwision/types-graphql
```

To generate a GraphQL schema, create a class with at least one public method with a `Query` attribute:

```
final class SomeApi {

    #[Query]
    public function ping(string $input): string
    {
        return strtoupper($input);
    }
}
```

Now, this API can be used to create a GraphQL schema:

```
// ...
$generator = new GraphQLGenerator();
$schema = $generator->generate(SomeApi::class)->render();

assert($schema === 'type Query {
  ping(input: String!): String!
}
');
```

### Advanced types

[](#advanced-types)

If you API class refers to more complex types (using attributes from the [wwwision/types](https://github.com/bwaidelich/types) package) in method parameters or return types, they will be added to the schema too.

**Example: Advanced types**1. Given you have the following classes defined:

```
#[StringBased]
final class GivenName {
    private function __construct(public readonly string $value) {}
}

#[StringBased]
final class FamilyName {
    private function __construct(public readonly string $value) {}
}

final class FullName {
    public function __construct(
        public readonly GivenName $givenName,
        public readonly FamilyName $familyName,
    ) {}
}

#[Description('honorific title of a person')]
enum HonorificTitle
{
    #[Description('for men, regardless of marital status, who do not have another professional or academic title')]
    case MR;
    #[Description('for married women who do not have another professional or academic title')]
    case MRS;
    #[Description('for girls, unmarried women and married women who continue to use their maiden name')]
    case MISS;
    #[Description('for women, regardless of marital status or when marital status is unknown')]
    case MS;
    #[Description('for any other title that does not match the above')]
    case OTHER;
}

#[Description('A contact in the system')]
final class Contact {
    public function __construct(
        public readonly HonorificTitle $title,
        public readonly FullName $name,
        #[Description('Whether the contact is registered or not')]
        public bool $isRegistered = false,
    ) {}
}

#[ListBased(itemClassName: Contact::class)]
final class Contacts {
    private function __construct(private readonly array $contacts) {}
}
```

2. ...and this API class:

```
// ...
final class SomeApi {

    #[Query]
    public function findContactsByFamilyName(FamilyName $familyName): Contacts
    {
        // ...
    }

    #[Mutation]
    public function addContact(Contact $newContact): bool
    {
        // ...
    }

}
```

3. The GraphQL schema is more verbose now:

```
// ...
$generator = new GraphQLGenerator();
$schema = $generator->generate(SomeApi::class)->render();

$expectedSchema = generate(SomeApi::class)->render();

$expectedSchema =  **Note**The signature of the custom resolver closure has to contain the extended type as first argument and specify the return type, for example: `new CustomResolver('SomeObject', 'someCustomField', fn (SomeObject $thisIsRequired, string $thisIsOptional): bool => true)`

**Example: Custom resolvers**```
final class User {
    public function __construct(
        public readonly string $givenName,
        public readonly string $familyName,
    ) {}
}

#[ListBased(itemClassName: User::class)]
final class Users {
}

final class SomeApi {
    #[Query]
    public function users(): ?Users
    {
        // ...
    }
}

$generator = new GraphQLGenerator();
$customResolvers = CustomResolvers::create(new CustomResolver('User', 'fullName', fn (User $user): string => $user->givenName . ' ' . $user->familyName));
$schema = $generator->generate(SomeApi::class, $customResolvers)->render();

$expectedSchema =
