Open simonworkhouse opened 2 days ago
A potential fix would be to update Illuminate\Foundation\Application::booted($callback)
with the following:
public function booted($callback)
{
if ($this->isBooted()) {
$callback($this);
} else {
$this->bootedCallbacks[] = $callback;
}
}
I just don't have the time available to write tests and submit a PR right now.
What's your actual use case for this?
Do you require me to provide you with a detailed use-case in order for this bug to be fixed? Because I can do that, but I just don't see it as being a constructive use of one's time.
In short, I discovered this issue while integrating packages maintained by separate developers, where both packages need to ensure that actions occur after application boot, and one of those packages also provides a mechanism for triggering callbacks after it has booted (although not actual package boot, but it's own concept of "booting" as it provides support for extensions/addons/plugins). Now the first package would either have to depend on the second always executing it's booted callbacks after application boot (which is risky and not guaranteed), or it could simply add it's own application booted callbacks that are added during the second packages booted callbacks.
That being said, do please let me know if you require a detailed use-case.
Do you require me to provide you with a detailed use-case in order for this bug to be fixed?
ServiceProvider::booted()
for similar use case (I would assume similar but would need additional information as requested to confirm) https://github.com/laravel/framework/blob/59bf3bfc0f9acce5b1d11c08ddba01f82201c678/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.php#L53-L66I think we could either:
Option A: Swap lines 1105 and 1107 from the Illuminate\Foundation\Application@boot()
method:
IMO, the internal booted
variable should only become true
as the very last thing of the Application@boot()
method, until then, it is still "booting".
Option B: Change the Illuminate\Foundation\Application@boot()
method from:
to:
public function booted($callback)
{
if ($this->isBooted()) {
$callback($this);
} else {
$this->bootedCallbacks[] = $callback;
}
}
This is more cumbersome, as the callbacks are no longer cached, but as $this->isBooted()
returns true
while running $this->fireAppCallbacks($this->bootedCallbacks)
(without option A), the inner callback gets called right away while also being added to the array, thus later being called twice.
I think both "fixes" could be considered. Unless we want to keep track of $this->bootedCallbacks
for some reason, such as Octane.
Currently, from my understanding, the $this->bootedCallbacks
array isn't iterated anymore after the Application is booted.
For the record, I tested both options on a local fresh Laravel project, and both seem to resolve the issue.
Unfortunately, I won't be able to work on a proper PR for the next few days. If someone wants to give it a shot, it would be great.
Laravel Version
11.33.2
PHP Version
8.2.23
Database Driver & Version
SQLite
Description
Booted callbacks are being called twice when they are registered within another booted callback.
Steps To Reproduce
Create a fresh
laravel/laravel
project and add the following to theregister
method ofApp\Providers\AppServiceProvider
:Execute
php artisan about
and it will show the following: