# Extending Lighthouse

Lighthouse offers various extension points which can be utilized by package developers as well as end users.

# The Event System

Lighthouse offers a unified way of hooking into the complete execution lifecycle through Laravel's event system (opens new window). You may use any Service Provider to register listeners.

A complete list of all dispatched events is available in the events API reference.

# Adding Directives

Add your custom directives to Lighthouse by listening for the RegisterDirectiveNamespaces event.

namespace SomeVendor\SomePackage;

use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\ServiceProvider;
use Nuwave\Lighthouse\Events\RegisterDirectiveNamespaces;

class SomePackageServiceProvider extends ServiceProvider
{
    public function boot(Dispatcher $dispatcher): void
    {
        $dispatcher->listen(
            RegisterDirectiveNamespaces::class,
            function (RegisterDirectiveNamespaces $registerDirectiveNamespaces): string {
                // May also return an iterable with multiple strings if needed
                return 'SomeVendor\SomePackage\Directives';
            }
        );
    }

# Changing the default resolver

The first priority when looking for a resolver is always given to FieldResolver directives.

After that, Lighthouse attempts to find a default resolver.

The interface \Nuwave\Lighthouse\Support\Contracts\ProvidesResolver (opens new window) is expected to provide a resolver in case no resolver directive is defined for a field.

If the field is defined on the root Query or Mutation types, Lighthouse's default implementation looks for a class with the capitalized name of the field in the configured default location and calls its __invoke method.

Non-root fields fall back to webonyx's default resolver (opens new window). You may overwrite this by passing a callable to \GraphQL\Executor\Executor::setDefaultFieldResolver.

When the field is defined on the root Subscription type, the \Nuwave\Lighthouse\Support\Contracts\ProvidesSubscriptionResolver (opens new window) interface is used instead.

# Use a custom GraphQLContext

The context is the third argument of any resolver function.

You may replace the default \Nuwave\Lighthouse\Schema\Context with your own implementation of the interface Nuwave\Lighthouse\Support\Contracts\GraphQLContext. The following example is just a starting point of what you can do:

namespace Nuwave\Lighthouse\Schema;

use Illuminate\Http\Request;
use Illuminate\Contracts\Auth\Authenticatable;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class MyContext implements GraphQLContext
{
    /**
     * An instance of the incoming HTTP request.
     *
     * @var \Illuminate\Http\Request
     */
    public $request;

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    /**
     * Get instance of request.
     *
     * @return \Illuminate\Http\Request
     */
    public function request(): Request
    {
        return $this->request;
    }

    /**
     * Get instance of authenticated user.
     *
     * May be null since some fields may be accessible without authentication.
     *
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function user(): ?Authenticatable
    {
        // TODO implement yourself
    }
}

You need a factory that creates an instance of \Nuwave\Lighthouse\Support\Contracts\GraphQLContext. This factory class needs to implement \Nuwave\Lighthouse\Support\Contracts\CreatesContext.

namespace App\GraphQL;

use Illuminate\Http\Request;
use Nuwave\Lighthouse\Support\Contracts\CreatesContext;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class MyContextFactory implements CreatesContext
{
    /**
     * Generate GraphQL context.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Nuwave\Lighthouse\Support\Contracts\GraphQLContext
     */
    public function generate(Request $request): GraphQLContext
    {
        return new MyContext($request);
    }
}

Rebind the interface in a service provider (e.g. your AppServiceProvider or a new GraphQLServiceProvider):

public function register(): void
{
    $this->app->bind(
        \Nuwave\Lighthouse\Support\Contracts\CreatesContext::class,
        \App\MyContextFactory::class
    );
}