Skip to content

Conversation

ruudk
Copy link
Collaborator

@ruudk ruudk commented Oct 3, 2025

Note

This is an alternative (and I think better) approach to:

This allows transforming the object value after type resolution.

This is useful when you have a single entity that needs different representations. For example, when your data layer returns a generic PetEntity with a type discriminator, but your GraphQL schema has separate Dog and Cat types.

Example:

$PetType = new InterfaceType([
    'name' => 'Pet',
    'resolveType' => static function (PetEntity $objectValue): string {
        if ($objectValue->type === 'dog') {
            return 'Dog';
        }
        return 'Cat';
    },
    'resolveValue' => static function (PetEntity $objectValue) {
        if ($objectValue->type === 'dog') {
            return new Dog($objectValue->name, $objectValue->woofs);
        }
        return new Cat($objectValue->name, $objectValue->meows);
    },
    'fields' => ['name' => ['type' => Type::string()]],
]);

Now field resolvers receive the properly typed Dog or Cat object instead of the generic PetEntity,
allowing for type-safe resolution without needing to transform objects before they reach the type
resolver.

Common use cases:

  • Database polymorphism (single table with type column)
  • External APIs returning generic objects with type discriminators

@ruudk
Copy link
Collaborator Author

ruudk commented Oct 3, 2025

Instead of calling it resolveValue we could also go with transformValue indicating that this is about transforming the value from A to B.

@ruudk ruudk force-pushed the introduce-resolve-value branch from 26e8d73 to 80ba591 Compare October 3, 2025 12:11
@ruudk ruudk requested review from simPod and spawnia October 6, 2025 18:40
Copy link
Collaborator

@spawnia spawnia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name resolveValue makes sense to me, especially considering the symmetry with resolveType.

This allows transforming the object value after type resolution.

This is useful when you have a single entity that needs different representations. For example, when
your data layer returns a generic `PetEntity` with a type discriminator, but your GraphQL schema has
separate `Dog` and `Cat` types.

Example:

```php
$PetType = new InterfaceType([
    'name' => 'Pet',
    'resolveType' => static function (PetEntity $objectValue): string {
        if ($objectValue->type === 'dog') {
            return 'Dog';
        }
        return 'Cat';
    },
    'resolveValue' => static function (PetEntity $objectValue) {
        if ($objectValue->type === 'dog') {
            return new Dog($objectValue->name, $objectValue->woofs);
        }
        return new Cat($objectValue->name, $objectValue->meows);
    },
    'fields' => ['name' => ['type' => Type::string()]],
]);

Now field resolvers receive the properly typed Dog or Cat object instead of the generic PetEntity,
allowing for type-safe resolution without needing to transform objects before they reach the type
resolver.

Common use cases:
- Database polymorphism (single table with type column)
- External APIs returning generic objects with type discriminators
@ruudk ruudk force-pushed the introduce-resolve-value branch from 80ba591 to a753f1c Compare October 7, 2025 17:45
@spawnia spawnia merged commit 93b8210 into webonyx:master Oct 8, 2025
18 checks passed
spawnia added a commit that referenced this pull request Oct 8, 2025
@spawnia
Copy link
Collaborator

spawnia commented Oct 8, 2025

Released with https://github.com/webonyx/graphql-php/releases/tag/v15.25.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants