buismaarten / laravel-layered-environment
Laravel package for layered environment variable overrides.
Package info
github.com/buismaarten/laravel-layered-environment
pkg:composer/buismaarten/laravel-layered-environment
Requires
- php: ^8.3
- laravel/framework: ^13.0
- vlucas/phpdotenv: ^5.6.1
Requires (Dev)
- orchestra/testbench: ^11.1
- phpunit/phpunit: ^12.5
README
Laravel Layered Environment allows your Laravel application to load environment variables from multiple .env files.
Instead of maintaining a single .env file for every environment, you can split your environment configuration across multiple files and let Laravel merge them together according to a predictable precedence order.
Why?
Laravel applications commonly use a single .env file containing environment-specific configuration.
As an application grows, this can become inconvenient. Some values are shared between environments and should be committed to version control, while other values are specific to a developer, server, or deployment and should remain outside the repository.
Laravel Layered Environment introduces a simple convention for separating these values:
.env
.env.override
.env.testing
.env.testing.override
.env.production
.env.production.override
This allows you to keep non-sensitive defaults in version control while storing sensitive or machine-specific values in an uncommitted override file.
Requirements
- PHP 8.3+
- Laravel 13.x
Installation
Install the package via Composer:
composer require buismaarten/laravel-layered-environment
After installing the package, register the package's environment loader in bootstrap/app.php.
<?php use Illuminate\Foundation\Application; $app = Application::configure(basePath: dirname(__DIR__)) // ... ->create(); $app->singleton( Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, LaravelLayeredEnvironment\LoadEnvironmentVariables::class, ); return $app;
That's all that is required to enable layered environment files.
Usage
Laravel Layered Environment follows Laravel's normal environment variable handling. You can continue using env() and config() exactly as you normally would.
For example, given the following files:
.env
.env.override
.env.production
.env.production.override
the application will load them as layers.
Environment files
The base .env file contains the default values for the application:
APP_NAME="My Application" APP_ENV=production APP_DEBUG=false CACHE_STORE=database QUEUE_CONNECTION=database
The environment-specific .env.production file can contain values that apply to all production deployments:
APP_ENV=production APP_DEBUG=false CACHE_STORE=redis QUEUE_CONNECTION=redis
Finally, .env.production.override can contain values specific to a particular server or deployment:
APP_URL=https://example.com REDIS_HOST=10.0.0.10 REDIS_PASSWORD=super-secret-password
When the application runs in the production environment, all three files are loaded in order.
Environment File Precedence
Environment files are loaded from least specific to most specific.
For a production application, the order is:
.env
↓
.env.override
↓
.env.production
↓
.env.production.override
If the same variable is defined in multiple files, the value from the file loaded last takes precedence.
For example:
# .env APP_DEBUG=false APP_NAME="My Application"
# .env.production APP_DEBUG=true
# .env.production.override APP_DEBUG=false
The resulting value is:
APP_DEBUG=false
This gives you a simple way to define defaults once and override them only where necessary.
Recommended .gitignore
Remove any existing .env-related entries from your .gitignore that would prevent shared environment files (such as .env, .env.testing, or .env.production) from being committed.
Add the following to your .gitignore to keep overrides and environment-specific overrides out of version control:
.env.override .env.*.override
This allows the shared environment files to be committed while keeping local and deployment-specific overrides out of version control.
Never commit passwords, API keys, private keys, or other secrets to your repository. An override file being ignored by Git does not prevent it from being leaked through other means, so treat these files as sensitive.
Example Project Structure
A project using Laravel Layered Environment might look like this:
├── .env
├── .env.override
├── .env.testing
├── .env.testing.override
├── .env.production
├── .env.production.override
├── app/
├── bootstrap/
│ └── app.php
├── config/
├── resources/
└── ...
With the following files committed:
.env
.env.testing
.env.production
And the following files ignored:
.env.override
.env.testing.override
.env.production.override
This provides a clean separation between shared configuration and deployment-specific configuration.
License
The MIT License (MIT). Please see the LICENSE for more information.