GraphQLBundle icon indicating copy to clipboard operation
GraphQLBundle copied to clipboard

Type-hint DebugCommand constructor against interfaces?

Open BenMorel opened this issue 4 years ago • 0 comments

Q A
Bug report? no
Feature request? yes
BC Break report? no
RFC? yes
Version/Branch 0.13.6

Hi, we're decorating the MutationResolver and ResolverResolver to log, wrap some exceptions in custom responses, etc.:

services:
  App\Infrastructure\GraphQL\Resolver\MutationResolver:
    decorates: Overblog\GraphQLBundle\Resolver\MutationResolver
    arguments:
      $baseResolver: '@.inner'
use Overblog\GraphQLBundle\Resolver\MutationResolver as BaseMutationResolver;

class MutationResolver implements FluentResolverInterface
{
    private BaseMutationResolver $baseResolver;

    public function __construct(BaseMutationResolver $baseResolver)
    {
        $this->baseResolver = $baseResolver;
    }

    public function resolve($input)
    {
        try {
            $output = $this->baseResolver->resolve($input);
        }

        // ...
    }

    // ...
}

This works perfectly fine, except for bin/console that now screams:

Overblog\GraphQLBundle\Command\DebugCommand::__construct(): Argument #2 ($mutationResolver) must be of type Overblog\GraphQLBundle\Resolver\MutationResolver, App\Infrastructure\GraphQL\
Resolver\MutationResolver given

Because this command's constructor is type-hinted against implementations instead of interfaces, the only way right now to decorate the resolvers is to extend the base resolvers, instead of being able to wrap them. In other words, inheritance instead of composition.

Would you accept a PR that either:

  • type-hints the 3 resolvers as FluentResolverInterface:
    public function __construct(
        FluentResolverInterface $typeResolver,
        FluentResolverInterface $mutationResolver,
        FluentResolverInterface $resolverResolver
    ) {
        parent::__construct();
        $this->typeResolver = $typeResolver;
        $this->mutationResolver = $mutationResolver;
        $this->resolverResolver = $resolverResolver;
    }
    
  • or adds 3 interfaces, one for each resolver:
    interface TypeResolverInterface extends FluentResolverInterface {}
    interface MutationResolverInterface extends FluentResolverInterface {}
    interface ResolverResolverInterface extends FluentResolverInterface {}
    
    public function __construct(
        TypeResolverInterface $typeResolver,
        MutationResolverInterface $mutationResolver,
        ResolverResolverInterface $resolverResolver
    ) {
        parent::__construct();
        $this->typeResolver = $typeResolver;
        $this->mutationResolver = $mutationResolver;
        $this->resolverResolver = $resolverResolver;
    }
    

Thanks in advance for your feedback!

BenMorel avatar Jun 22 '21 14:06 BenMorel