Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] Add before resolving callbacks #35228

Merged
merged 3 commits into from
Nov 16, 2020

Conversation

lorisleiva
Copy link
Contributor

Description

As mentioned in #35202, this PR enables us to hook some custom logic into the beginning of the container resolution — i.e. before an instance as been resolved from the provided abstract.

Usage

It uses the same conventions as the $(after)ResolvingCallbacks and $global(After)ResolvingCallbacks to register and trigger the callbacks.

// Adds a specific before resolving callback.
$this->app->beforeResolving(MyService::class, function ($abstract, $parameters, $app) {
    // ...
});

// Adds a global before resolving callback.
$this->app->beforeResolving(function ($abstract, $parameters, $app) {
    // ...
});

Advanced usage

These before resolving callbacks can be used as a way to dynamically add specific extenders and, therefore, remove the need for #35202.

For example, this global extender...

$this->app->extend(function ($instance, $app) {
    if (! $app->isProduction() && $instance instanceof CanBeFaked) {
        return FakeServiceDecorator($instance);
    }

    return $instance;
});

... could be achieve with the following before resolving callback:

$this->app->beforeResolving(function ($abstract, $parameters, $app) {
    if ($app->isProduction() || ! is_subclass_of($abstract, CanBeFaked::class) || $app->resolved($abstract)) {
        return;
    }

    $app->extend($abstract, function ($instance) {
        return FakeServiceDecorator($instance);
    });
});

Since the specific before resolving callbacks already check for inheritance, this could be refactored to:

$this->app->beforeResolving(CanBeFaked::class, function ($abstract, $parameters, $app) {
    if ($app->isProduction() || $app->resolved($abstract)) {
        return;
    }

    $app->extend($abstract, function ($instance) {
        return FakeServiceDecorator($instance);
    });
});

Note the use of $app->resolved($abstract), to ensure we do not add the same extender multiple times.

Backward compatibility

This PR does not add any breaking changes.

It triggers new types of callbacks that wouldn't have been registered before.

@lorisleiva lorisleiva changed the title Add before resolving callbacks [8.x] Add before resolving callbacks Nov 15, 2020
@taylorotwell taylorotwell merged commit 6e9cd67 into laravel:8.x Nov 16, 2020
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