php artisan config:cache — what it does and when it breaks
Concept
php artisan config:cache compiles all config files into a single PHP file (bootstrap/cache/config.php), dramatically improving boot time in production. Understanding what it does — and its critical limitations — is essential for deployment.
What config:cache does:
- Loads all files in
config/. - Evaluates all
env()calls at cache-time using the current.envvalues. - Writes the resolved PHP array to
bootstrap/cache/config.php. - Subsequent requests read from the cache file instead of loading all config files.
The critical limitation: After config:cache runs, the .env file is NOT read anymore. env() calls return null (or the second argument default). This is intentional — the values are baked into the cache.
Consequence: Any code that calls env() outside of a config file WILL break after config:cache. This includes service classes, middleware, anything that directly calls env(). Always use config() in application code.
Detecting the issue:
- Symptom: Everything works locally but breaks in production.
- Cause: Local dev doesn't usually run
config:cache; production does. - Fix: Move all
env()calls to config files, useconfig()everywhere else.
config:clear: Removes the cache file. Forces reload from config files and .env on next request.
Deployment workflow:
composer install --no-dev --optimize-autoloaderphp artisan config:cachephp artisan route:cachephp artisan view:cachephp artisan event:cache- Restart PHP-FPM workers
Code Example
# Cache all config files
php artisan config:cache
# → bootstrap/cache/config.php created
# Clear config cache
php artisan config:clear
# → bootstrap/cache/config.php deleted
# Verify no env() calls exist outside config files
# (Enlightn checks this automatically)
grep -rn "env(" app/ --include="*.php" | grep -v config/
# Any results here are potential issues
# Check if config is cached (useful for debugging)
php artisan config:show app.debug # reads from cache or config<?php
// WRONG — env() in a service class (breaks after config:cache)
class StripeService
{
public function __construct()
{
$this->key = env('STRIPE_KEY'); // returns null after config:cache!
}
}
// CORRECT — use config() (always works, cached or not)
// In config/services.php:
// 'stripe' => ['key' => env('STRIPE_KEY')],
class StripeService
{
public function __construct()
{
$this->key = config('services.stripe.key'); // reads from cache or config
}
}
// Checking if config is cached at runtime
if (file_exists(base_path('bootstrap/cache/config.php'))) {
// Config is cached
}
// Artisan checks in deployment scripts
// php artisan about --only=cache -- shows cache status