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

[11.x] Alternative fix for booted callbacks being called twice #53695

Conversation

simonworkhouse
Copy link
Contributor

Fixes #53589

This is an alternative implementation of a fix submitted in the PR #53683

In consideration of potential breaking changes in the previous PR, this implementation still allows booted callbacks to be pushed onto the array while not calling the callback immediately if booted callbacks are currently being processed.

Booted callbacks which are added during the execution of other callbacks
are being called twice. This commit is an alternative inmplementation of
a fix for this issue. Originial PR laravel#53683
@rodrigopedra
Copy link
Contributor

rodrigopedra commented Nov 28, 2024

I'd only swap the last two lines on the Application@boot() method.

Before:

public function boot()
{
if ($this->isBooted()) {
return;
}
// Once the application has booted we will also fire some "booted" callbacks
// for any listeners that need to do work after this initial booting gets
// finished. This is useful when ordering the boot-up processes we run.
$this->fireAppCallbacks($this->bootingCallbacks);
array_walk($this->serviceProviders, function ($p) {
$this->bootProvider($p);
});
$this->booted = true;
$this->fireAppCallbacks($this->bootedCallbacks);
}

After:

public function boot()
{
    if ($this->isBooted()) {
        return;
    }

    // Once the application has booted we will also fire some "booted" callbacks
    // for any listeners that need to do work after this initial booting gets
    // finished. This is useful when ordering the boot-up processes we run.
    $this->fireAppCallbacks($this->bootingCallbacks);

    array_walk($this->serviceProviders, function ($p) {
        $this->bootProvider($p);
    });

    $this->fireAppCallbacks($this->bootedCallbacks);

    $this->booted = true;
}

As I commented in the issue, it solves the issue, and IMO, it is the less intrusive option.

Also, to me, it makes more sense to mark the application as booted as the very last thing on the Application@boot() method.

In other words: if there are remaining callbacks to be run, the application is not yet booted.

@simonworkhouse
Copy link
Contributor Author

@rodrigopedra I wholeheartedly agree that would be the better solution, although my only concern would be that it could be a breaking change for any app that expects App::isBooted() to return true during a callback.

@rodrigopedra
Copy link
Contributor

rodrigopedra commented Nov 28, 2024

@simonworkhouse that is true.

Although Application@isBooted() is not part of the Illuminate\Contracts\Foundation\Application contract, and it is only called within the Application class within the framework.

Also, IMO, checking Application@isBooted() within a callback registered as a "booted" callback seems very unlikely.

Nonetheless, maybe this could be sent to master, 12.x is around the corner anyway.


EDIT: by sending it to master, I mean to also add a note on the upgrade guide about the change

@taylorotwell
Copy link
Member

I'm just not sure I have an appetite for changing this behavior right now.

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.

Application booted callbacks called twice
3 participants