phanan/cascading-config
Laravel package that brings cascading configuration to your apps: split settings into layered files where environment-specific values override the defaults, keeping large configs organized and avoiding duplication across environments.
phanan/cascading-config restores Laravel 4–style environment config folders to Laravel 5: a base config/*.php tree plus an environment-specific overlay in config/{APP_ENV}/*.php. It is a small, single-purpose package (archived, ~55 stars, no dependents), so treat it as a legacy-app convenience rather than a foundation for new work.
Minimal setup:
composer require phanan/cascading-config
providers array in config/app.php so it runs before providers that read config during register():
'providers' => [
Phanan\CascadingConfig\CascadingConfigServiceProvider::class,
// ...
],
Laravel 5.5+ auto-discovery may pick it up, but manual registration at the top is safer because provider order is otherwise not guaranteed..env:
APP_ENV=local
config/local/app.php:
<?php
return [
'debug' => true,
'name' => 'My App (local)',
];
php artisan tinker
>>> config('app.debug'); // true
>>> app()->environment(); // "local"
First real use case: stop copying entire config files around for local development. Keep config/mail.php as the shared source of truth and add config/local/mail.php with only 'driver' => 'log', or config/local/database.php with a local socket/host. The base file remains the canonical schema; the overlay carries only the deltas for that environment.
Where to look first in the repo: the service provider (to understand when the merge happens relative to config loading), then the README for the exact folder convention and supported Laravel versions. Because the project is archived, read the source rather than assuming behavior.
Base + sparse overlay. The productive pattern is: full config files in config/, minimal partial arrays in config/{env}/. Never duplicate a whole file into the overlay; that defeats the purpose and creates drift. A useful convention is to leave a one-line comment at the top of each overlay file naming the environment it targets.
Environment matrix. For a typical Laravel 5 app, keep overlays for the environments you actually boot:
config/
app.php
database.php
mail.php
local/
app.php
mail.php
testing/
database.php
mail.php
staging/
app.php
local gets debug/log-mail; testing gets sqlite/in-memory and array mail; staging mirrors production but with verbose logging. Production usually needs no overlay beyond .env secrets.
Separate structural config from secrets. Use .env for credentials and host-specific secrets (DB_PASSWORD, API keys), and use the cascade for structural, array-shaped settings that environment variables express poorly: feature flag arrays, multi-connection definitions, queue topology, log stacks. This is the package's main justification over pure .env usage.
Testing overrides. config/testing/database.php with an in-memory SQLite connection and config/testing/mail.php with the array or log driver is a clean way to keep test config out of phpunit.xml and out of TestCase::setUp(). Ensure APP_ENV=testing is what PHPUnit actually boots with; otherwise the overlay silently does nothing.
Provider ordering. Any provider that reads config() in its own register() (common in packages that build bindings from config) must run after this one. Keep the cascading provider first and audit third-party providers that capture config early. If you see base values leaking into a service that should have the overlay, ordering is the usual cause.
Document the overlay contract. Because the merge is implicit, add a short section to the project README listing which keys each environment overlay is allowed to touch. This prevents the overlay from becoming a second, undocumented config system.
Keep overlays reviewable. Commit shared environment overlays (staging, testing) to version control. For per-developer local overlays, either commit harmless defaults or gitignore the folder—but make sure the folder's absence is a supported no-op (it is, in practice, a silent skip).
.env plus a small AppServiceProvider-based overlay if you truly need per-environment arrays. On a legacy 5.x app, pin the version in composer.json and avoid composer update surprises.array_merge, which replaces nested arrays wholesale rather than deep-merging them. Overriding database.connections.mysql.host in config/local/database.php can wipe every other connection unless you redeclare the full connections block. Verify the package's merge behavior in the source before relying on partial nested overrides; if it is shallow, either restate the whole nested key or fork the provider to use array_replace_recursive.config:cache interacts badly. php artisan config:cache flattens config into bootstrap/cache/config.php and bypasses the normal file-loading path. Depending on where the provider hooks in, the cascade may be applied on top of stale cached values, or skipped entirely, producing "works locally, broken in deploy" behavior. Always run php artisan config:clear before debugging, and re-run config:cache in each environment if you cache. When in doubt, disable config caching for apps that depend on this package.APP_ENV defaults to production. If .env is missing or APP_ENV is unset, app()->environment() reports production, so a config/production/ overlay will be applied—often the opposite of what a developer expects on a fresh checkout. Make APP_ENV explicit in .env.example.config/locl/) or a file named app.php.bak produces no error; the base config simply wins. Debug by checking app()->environment() and config('app.debug') in tinker, then confirm the overlay file returns an array (a syntax error in the overlay is the other common failure).config/app.php and re-test after adding new packages..env; overlays should hold non-secret structure.env() calls in the base config, or move the deltas into a service provider that reads a single APP_ENV-keyed array. Doing this before a Laravel upgrade is cheaper than carrying an archived package across a major version boundary.How can I help you explore Laravel packages today?