0

Environment-specific config — config/database.php patterns

Intermediate5 min read·lv-05-004

Concept

Laravel's config system supports environment-specific configuration through .env files, environment checks, and conditional config values. The config/database.php file demonstrates the pattern: one file, multiple driver configurations, with .env determining which to use at runtime.

Multi-driver config pattern: Config files typically define configurations for all environments/drivers, using .env to select the active one:

php
'default' => env('DB_CONNECTION', 'mysql'), // active connection
'connections' => ['sqlite' => [...], 'mysql' => [...], 'pgsql' => [...]], // all options

Environment-specific .env files: Laravel supports .env.testing (loaded when APP_ENV=testing), and .env.{environment} files. PHPUnit tests automatically use APP_ENV=testing and load .env.testing if it exists.

Config per environment via code: Avoid if (app()->environment('production')) { ... } inside config files — it creates coupling and defeats caching. Instead, read from env:

php
'debug' => env('APP_DEBUG', false), // controlled entirely by .env

Service-specific config patterns: config/services.php holds third-party API credentials per service. Each environment has different API keys. The structure is the same; only the .env values change.

config/logging.php per-channel configuration: Each log channel is fully configured in the file. LOG_CHANNEL=stack in production, LOG_CHANNEL=single in testing.

Code Example

php
<?php
// config/database.php — universal pattern for multi-environment databases
return [
    'default' => env('DB_CONNECTION', 'mysql'), // .env: DB_CONNECTION=sqlite for local

    'connections' => [
        // Local development — SQLite (no server needed)
        'sqlite' => [
            'driver'                  => 'sqlite',
            'database'                => env('DB_DATABASE', database_path('database.sqlite')),
            'prefix'                  => '',
            'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
        ],

        // Staging/Production — MySQL
        'mysql' => [
            'driver'      => 'mysql',
            'host'        => env('DB_HOST', '127.0.0.1'),
            'port'        => env('DB_PORT', '3306'),
            'database'    => env('DB_DATABASE', 'laravel'),
            'username'    => env('DB_USERNAME', 'root'),
            'password'    => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset'     => 'utf8mb4',
            'collation'   => 'utf8mb4_unicode_ci',
            'strict'      => true,
            'engine'      => null,
            'options'     => extension_loaded('pdo_mysql') ? array_filter([
                \PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],
    ],

    'migrations' => 'migrations',
    'redis' => ['...'],
];
bash
# .env.local
DB_CONNECTION=sqlite
DB_DATABASE=/path/to/database.sqlite

# .env.staging
DB_CONNECTION=mysql
DB_HOST=staging-db.internal
DB_DATABASE=myapp_staging
DB_USERNAME=myapp
DB_PASSWORD=staging_password_here

# .env.testing (used by phpunit)
DB_CONNECTION=sqlite
DB_DATABASE=:memory:
APP_ENV=testing
php
// phpunit.xml — sets environment for tests
// <env name="APP_ENV" value="testing"/>
// <env name="DB_CONNECTION" value="sqlite"/>
// <env name="DB_DATABASE" value=":memory:"/>