overridingdirectiveextendlaravel-lighthouse

Extend and override default lighthouse directive


Is there anyway that I can override a directive like: src/Schema/Directives/WhereDirective.php for instance this doesn't support some methods on my custom builder, I know I can make another directive and extend this like @myWhere but that's dirty, would be nice to be able to override the @where itself.

I've searched around but nothing was found about this sadly!


Solution

  • I found the solution. according to https://lighthouse-php.com/5/custom-directives/getting-started.html#register-directives

    When Lighthouse encounters a directive within the schema, it starts looking for a matching class in the following order:

    1. User-defined namespaces as configured in config/lighthouse.php, defaults to App\GraphQL\Directives
    2. The RegisterDirectiveNamespaces event is dispatched to gather namespaces defined by plugins, extensions or other listeners
    3. Lighthouse's built-in directive namespace.

    So it did seem like override could be possible, and it was.

    I haven't tried first method (App\GraphQL\Directive...) but that probably would work too, I went with the second method the RegisterDirectiveNamespaces event, since I was writing a package.

    Make all your directives in the same folder under one namespace eg:

    namespace SteveMoretz\Something\GraphQL\Directives;
    

    Now in a service provider (Can be your package's service provider or AppServiceProvider or any service provider you get the idea.) register that namespace your directives are under.

    use Illuminate\Contracts\Events\Dispatcher;
    use Nuwave\Lighthouse\Events\RegisterDirectiveNamespaces;
    
    class ScoutGraphQLServiceProvider {
        public function register(Dispatcher $dispatcher) {
            $dispatcher->listen(
                RegisterDirectiveNamespaces::class,
                static function (): string {
                    return "SteveMoretz\Something\GraphQL\Directives";
                }
            );
        }
    }
    

    That's it so for an example I have overridden the @where directive, first I created a file named as original WhereDirective.php then put these contents in it:

    <?php
    
    namespace SteveMoretz\Something\GraphQL\Directives;
    
    use Nuwave\Lighthouse\Scout\ScoutBuilderDirective;
    use Nuwave\Lighthouse\Support\Contracts\ArgBuilderDirective;
    use Nuwave\Lighthouse\Schema\Directives\BaseDirective;
    use Nuwave\Lighthouse\Schema\Directives\WhereDirective as WhereDirectiveOriginal;
    use Nuwave\Lighthouse\Support\Contracts\FieldResolver;
    
    class WhereDirective extends WhereDirectiveOriginal
    {
        public function handleBuilder($builder, $value): object
        {
            $clause = $this->directiveArgValue('clause', 'where');
    
            // do some other stuff too... my custom logic 
    
            return $builder->{$clause}(
                $this->directiveArgValue('key', $this->nodeName()),
                $this->directiveArgValue('operator', '='),
                $value
            );
        }
    }
    

    Now whenever we use @where my custom directive runs instead of the original one, but be careful what you do in this directive don't alter the whole directive try to extend the original and add more options to it, otherwise you would end up confusing yourself later!