percymamedy/laravel-dev-booter
laravel-dev-booter streamlines Laravel package development by automatically discovering and registering your local package service providers in a host app. Skip manual config edits and boot packages instantly for faster, smoother build-test cycles.
Install the package.
composer require percymamedy/laravel-dev-booter
Laravel 5.5+ auto-discovers Percymamedy\LaravelDevBooter\LaravelDevBooterServiceProvider. On older versions add it to config/app.php manually.
Publish the config.
php artisan vendor:publish --provider="Percymamedy\LaravelDevBooter\LaravelDevBooterServiceProvider"
This produces config/laravel-dev-booter.php, which defines the folders the package scans and the environment value that gates "prod."
Where to look first.
config/laravel-dev-booter.php — folder paths and the environment mappingapp/Providers/Prod — provider classes that only boot when APP_ENV=productionapp/Providers/Dev — provider classes that boot everywhere elseFirst use case. Take an integration you only need on production — Sentry, New Relic, Bugsnag, a CDN warmer — and remove it from config/app.php. Drop the class into app/Providers/Prod/ instead. On boot the package scans that folder and registers each provider only when the app is in production. Dev providers work the same way in reverse.
Verify:
php artisan tinker --execute="dump(array_keys(app()->getLoadedProviders()));"
You should see the Prod provider absent under APP_ENV=local and present under APP_ENV=production. The package also ships artisan generators (make:prod-provider, make:dev-provider) that scaffold classes into the correct folder and namespace.
One provider per external service. This is the pattern the package is designed for. Keep config/app.php for framework plumbing and put monitoring, logging, APM, and paid integrations into named Prod providers.
Drive the environment off config, not literals. If your team uses prod, staging, or live instead of production, change it once in config/laravel-dev-booter.php. Everything in the folder inherits the gate.
Coarse switch (folder) + fine switch (config). A service is prod-only in principle but might be disabled per account. Keep it in Prod and return early:
public function register()
{
if (! config('services.datadog.enabled')) {
return;
}
// register bindings here
}
Prod-only commands and asset publishing. These folders are a natural home for command registration that doesn't make sense on a laptop (data sync, billing reconciliation) and for publishing assets devs shouldn't see.
Deferred providers. If the integration is optional, implement DeferrableProvider. The package registers it like any other provider, and you pay no boot cost unless a binding is actually resolved.
Testing. Laravel tests run with APP_ENV=testing, so Prod providers won't load — usually what you want. When a test needs one, register it explicitly in setup:
$this->app->register(SentryServiceProvider::class);
Directory and namespace convention. Keep App\Providers\Prod\... for app/Providers/Prod/. Mixing paths and namespaces is the most common cause of "class not found" when adding a file.
When to choose the native path instead. Laravel already supports this with two lines:
// AppServiceProvider::register()
if ($this->app->environment('production')) {
$this->app->register(SentryServiceProvider::class);
}
For one or two services, skip the package. Its value is convention, folder organization, and the artisan generators — it earns its keep once you have half a dozen prod-only integrations and want them out of the main list.
Environment string mismatch. The majority of "my provider isn't loading" issues come from APP_ENV=prod in .env versus production in the gate config (or vice versa). Dump app()->environment() next to the config value before touching anything else.
Never put framework-critical providers here. Sessions, routing, events, auth, queue — if the folder scan misses one, the app won't boot. Restrict these folders to optional integrations that fail safe.
Registration order. Prod/Dev providers boot after the core config/app.php list. A provider in config/app.php cannot depend on a binding registered by a Prod provider. If ordering is sensitive, use manual registration inside AppServiceProvider::register() instead.
Stale compiled config after moving a provider. After dragging a provider out of config/app.php, run:
php artisan config:clear && php artisan config:cache
If you skip this, bootstrap/cache/config.php keeps pointing at the old location and the provider "disappears."
Fresh-deploy env var failures. A Prod provider that reads an env var or config key at registration will throw on a first deploy where that value isn't set yet. Null-guard and provide defaults so a boot doesn't take the app down.
Early error handling limits. If you use the folders for logging or error-reporting providers, remember they boot after the framework has already initialized its own error handling. Exceptions thrown before that point won't be caught by your handler. For those, use Laravel's withExceptions() / bootstrap hooks, not a Prod provider.
Don't confuse with composer package discovery. extra.laravel auto-discovery is for third-party packages. This package is for your providers. Don't move a vendor package's provider into Prod just to control its config — set it in config/services.php and toggle from there.
Directory scan cost. The scan runs every boot. It's cheap for a handful of files and opcache absorbs most of it, but if you expect dozens of providers, benchmark with php artisan config:cache in place.
Exercise prod locally without flipping .env. Use a second env file:
APP_ENV=production php artisan serve --env=production
This is safer than editing .env and forgetting to revert.
Maintenance risk. The package is small (~35 stars) and hooks into internal provider-registration behavior. Check compatibility when upgrading Laravel majors and keep the two-line native snippet as a fallback — migrating off is trivial if the package is abandoned.
Extension points are thin. The published config is the only real hook. Per-provider environment overrides ("runs on staging and prod") aren't supported — duplicate the class into both folders or register it manually for those cases.
How can I help you explore Laravel packages today?