symfony/dotenv
Symfony Dotenv parses .env files and loads variables into $_ENV/$_SERVER for local development and configuration. Supports loading multiple files, overriding existing vars, and environment-specific .env.local/.env.$APP_ENV settings.
Install the package:
composer require symfony/dotenv
Load .env in bootstrap/app.php (before Laravel’s bootstrapping):
use Symfony\Component\Dotenv\Dotenv;
$dotenv = new Dotenv();
$dotenv->load(__DIR__.'/../.env');
Place this before require __DIR__.'/../vendor/autoload.php' to ensure variables are available early.
First Use Case:
Access variables via Laravel’s env() helper or $_ENV/$_SERVER:
$apiKey = env('API_KEY'); // Laravel's helper (preferred)
// OR
$apiKey = $_ENV['API_KEY'] ?? $_SERVER['API_KEY'] ?? null;
.env: Default environment file (commit to version control, exclude secrets)..env.local: Local overrides (add to .gitignore)..env.production: Production-specific settings (deployed via CI/CD).Use loadEnv() for Symfony’s convention-based loading:
$dotenv->loadEnv(__DIR__.'/../.env');
// Loads:
// .env
// .env.local
// .env.production.local (if APP_ENV=production)
Overwrite existing variables (e.g., for testing):
$dotenv->overload(__DIR__.'/../.env.testing');
Leverage ${VAR} syntax for derived values:
# .env
APP_URL=http://localhost:8000
API_BASE_URL=${APP_URL}/api/v1
Expands to http://localhost:8000/api/v1 when loaded.
env() HelperSymfony’s Dotenv populates $_ENV/$_SERVER, so Laravel’s env() helper works out-of-the-box. No additional configuration is needed.
Load multiple files in a specific order (e.g., defaults + overrides):
$dotenv->load(__DIR__.'/../.env.defaults');
$dotenv->overload(__DIR__.'/../.env.local');
Use overload() to inject secrets from environment variables or vaults:
// In deploy script
$dotenv->overload(__DIR__.'/../.env.production', [
'DB_PASSWORD' => getenv('DB_PASSWORD_FROM_CI'),
]);
debug:dotenvSymfony provides a built-in command to inspect loaded variables:
php bin/console debug:dotenv
Requires Symfony’s Console component (install via symfony/console).
Variable Corruption on Multiple Loads
load() once or overload() for updates.static $dotenv = null;
if (!$dotenv) {
$dotenv = new Dotenv();
$dotenv->load(__DIR__.'/../.env');
}
Self-Referencing Variables
${VAR} expansion fails if VAR depends on another unresolved variable.overload() to force resolution order.Escaped Dollar Signs Lost
\$ in values may be stripped during expansion (fixed in v8.0.7+)..env:
ESCAPED='This keeps \$ intact'
BOM (Byte Order Mark) Errors
.env files with BOM (common in Windows) throw exceptions (fixed in v7.1.5+).NUL Byte Placeholders
\0 may cause issues (fixed in v8.0.9+).trim() on values.Case Sensitivity
$_ENV is case-sensitive (DB_HOST ≠ db_host)..env (e.g., uppercase).Inspect Loaded Variables
var_dump($_ENV, $_SERVER);
or use Symfony’s debug:dotenv.
Check File Paths
Ensure paths are correct (e.g., __DIR__.'/../.env' vs. absolute paths).
Validate .env Syntax
Use an online validator or test with:
$dotenv->load(__DIR__.'/../.env'); // Throws exception on invalid syntax
Custom Variable Parsers
Extend Symfony\Component\Dotenv\Dotenv to support custom formats (e.g., JSON/YAML):
$dotenv = new Dotenv();
$dotenv->setParser(new CustomParser());
$dotenv->load(__DIR__.'/../config.yml');
Pre/Post-Processing Hook into variable loading via events (Symfony 6.0+):
$dotenv->on('env.parse', function (ParseEvent $event) {
$event->setValue('CUSTOM_VAR', 'processed');
});
Environment-Specific Logic
Use APP_ENV to conditionally load files:
$envFiles = [
'.env',
'.env.local',
".env.{$_ENV['APP_ENV'] ?? 'local'}.local",
];
$dotenv->load(...$envFiles);
.env once in bootstrap/app.php and reuse the instance.overload() for Updates: Faster than reloading entire files..env.local, .env.production, etc., from version control..gitignore:
# .gitignore
.env.local
.env*.local
.env before use (e.g., database credentials)..env files are readable only by the web server/user.How can I help you explore Laravel packages today?