In Laravel, when do the application's booting() and booted() callbacks and a provider's own booted() callback run, and what are they used for?
answer
- app booting: before any provider boots
- provider booting/booted wrap its boot()
- app booted: after every provider booted
- a late booted() callback runs at once
- routes load in a provider booted callback
basics
~10 s$app->booting() callbacks run before any provider's boot(); a provider's own booting() and booted() callbacks wrap that provider's boot(); $app->booted() callbacks run after every provider has booted, or immediately if added after boot.
solid answer
~40 sThe application's boot pass runs in a fixed order: all `$app->booting()` callbacks, then for each provider its own `booting()` callbacks, its `boot()` and its own `booted()` callbacks, then all `$app->booted()` callbacks. Application callbacks receive the application; provider callbacks are invoked through the container's `call()`, so they can type-hint services. `$app->booted()` is also safe to call late: if the app has already booted, the callback runs immediately, whereas a `booting()` callback added after boot has started never runs. Laravel uses these hooks itself: `withRouting()` registers the route provider in an app `booting` callback, that provider loads your route files in its own `booted` callback, and `withBroadcasting()` registers broadcast routes in an app `booted` callback. In `bootstrap/app.php`, the builder's `booting()`, `booted()` and `registered()` methods forward to the same hooks.
code
php · 20 lines<?php
namespace App\Providers;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\ServiceProvider;
class NewsletterServiceProvider extends ServiceProvider
{
public function boot(): void
{
// Runs after every provider, including the route provider, has booted.
$this->app->booted(function ($app) {
$count = count($app->make(Router::class)->getRoutes());
Log::debug("Newsletter routes checked: {$count} routes registered.");
});
}
}go deeper
Recall that booted() callbacks run after the app has started, and that most setup still belongs in a provider's boot().
Explain the full order: app booting, each provider's booting, boot and booted, then app booted, and which of them runs late registrations.
Use the hooks to fix ordering bugs, such as code that needs routes or another provider's configuration, without depending on provider order.
Keep startup ordering explicit and reviewable, limiting callback chains so new engineers can predict what runs when.
## Two levels of callbacks Laravel offers boot-phase hooks at two levels: - **Application level**: `$app->booting($cb)`, `$app->booted($cb)` and `$app->registered($cb)`, also reachable from `bootstrap/app.php` as `->booting()`, `->booted()` and `->registered()` on the application builder. - **Provider level**: `$this->booting($cb)` and `$this->booted($cb)` inside a service provider, attached to that provider only. They exist so code can run at a precise point relative to the rest of the startup, without depending on provider order. ## The exact order 1. Every configured provider's `register()` runs; then all **`registered`** callbacks fire. 2. `Application::boot()` fires all **app `booting`** callbacks. 3. For each registered provider, in order: 1. that provider's **`booting`** callbacks; 2. its `boot()` method, called through the container; 3. its **`booted`** callbacks. 4. The application marks itself booted and fires all **app `booted`** callbacks. | Hook | Runs | Receives | |---|---|---| | `$app->registered()` | after all configured providers registered | the application | | `$app->booting()` | before any provider boots | the application | | provider `booting()` | just before that provider's `boot()` | injected parameters | | provider `booted()` | just after that provider's `boot()` | injected parameters | | `$app->booted()` | after every provider has booted | the application | ## Late registration - `$app->booted()` checks whether the application has already booted; if so, it runs the callback **immediately**. Code can therefore call it at any time and be sure it runs once the app is ready. - `$app->booting()` has no such check. A callback added after the boot pass has started is stored but **never called**. - A provider registered after boot, for example a deferred provider loaded on demand, is booted straight away, including its own `booting` and `booted` callbacks. ## How the framework uses them - **Routing.** `withRouting()` in `bootstrap/app.php` registers the application's route provider from an app `booting` callback, so it is added after the configured providers and boots last. Without a route cache, that provider loads `routes/web.php` and the other route files in its own `booted` callback, after your `AppServiceProvider::boot()` has run, so route macros, patterns and model bindings defined there are ready in time. An app `booted` callback then refreshes the route name and action lookups. - **Broadcasting.** `withBroadcasting()` registers the broadcast auth routes and requires `routes/channels.php` in an app `booted` callback. - **JSON preference.** `prefersJsonResponses()` prepends its middleware to the HTTP kernel in an app `booted` callback. ## When to reach for them - Use a provider's plain **`boot()`** for almost everything; the callbacks are for ordering problems. - Use **`$app->booted()`** for work that must see the result of every provider's boot, such as inspecting registered routes or adjusting something another provider configured. - Use a provider's own **`booted()`** when a provider must finish its own setup first, as the route provider does. - Use **`$app->booting()`** to register something that must itself take part in the boot pass, typically another provider. - Avoid chains of callbacks that depend on one another's order; if two pieces of setup depend on each other, put them in the same method. ## Common mistakes - **Using `$app->booting()` from `boot()`.** The booting callbacks have already fired, so the callback silently never runs; `$app->booted()` is the late-safe choice. - **Expecting a provider's `booted()` to see every provider.** It runs right after that one provider's `boot()`, while later providers have not booted yet. - **Assuming routes exist in `boot()`.** Route files load after the configured providers boot, so code in `AppServiceProvider::boot()` that inspects routes does not yet see the application's own routes; move it to `$app->booted()`. - **Heavy work in callbacks.** Like `boot()` itself, every callback runs on every request and every command, so expensive work belongs in lazily resolved services. - **Forgetting cached routes.** With `route:cache`, route files are not loaded at all; the cached file is required in an app `booted` callback instead.
- In Laravel, what happens to a callback passed to $app->booting() from inside a provider's boot() method?It is stored but never called. The application fires its booting callbacks once, before the first provider boots, and `booting()` has no check for an application that is already booting or booted. Use `$app->booted()` instead, which runs late callbacks immediately.
- In Laravel, why can routes/web.php use a Route::pattern() defined in AppServiceProvider::boot()?The route provider that `withRouting()` registers is added in an app `booting` callback, after the configured providers, so it boots after `AppServiceProvider`. Without a route cache, it loads the route files in its own `booted` callback, by which point `AppServiceProvider::boot()` has already defined the pattern.
saying these in an interview costs you the question
- $app->booted() callbacks added after boot are silently ignored.
- A provider's booted() callback runs only after every provider has booted.
- $app->booting() callbacks run between register() and boot() of each provider.
- Route files load before AppServiceProvider::boot(), so route macros must go in register().
- Provider-level booted() callbacks cannot receive injected services.