环境配置与 .env 管理
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read331 words

环境配置与 .env 管理

.env 文件存放敏感配置(数据库密码、API Key),config/ 目录存放应用配置。两者的分工容易搞混——本节讲清楚 Laravel 的配置层次,以及在团队开发和生产环境中管理配置的最佳实践。


配置层次:.env vs config/

.env(环境变量)
↓ 通过 env() 函数读取
config/ 目录(PHP 配置数组)
↓ 通过 config() 函数读取
应用代码
// ❌ 不推荐:在应用代码里直接读 env()
$apiKey = env('STRIPE_SECRET');  // 配置缓存后读取的是空值!
// ✅ 推荐:在 config/ 中定义,应用代码用 config() 读取
// config/services.php
'stripe' => [
'key'    => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
],
// 应用代码:
$apiKey = config('services.stripe.secret');  // 始终正确

为什么 env() 在生产环境中不可靠? 执行 php artisan config:cache 后,.env 文件不再被读取——所有配置从缓存加载。env() 在缓存环境下只能返回 nullconfig() 不受此影响。


TaskFlow 的 .env 配置

# .env(开发环境示例)
APP_NAME="TaskFlow"
APP_ENV=local          # local / staging / production
APP_KEY=base64:...     # php artisan key:generate 生成
APP_DEBUG=true         # 生产环境必须为 false
APP_URL=http://localhost:8000
APP_TIMEZONE=Asia/Shanghai
# 数据库
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=taskflow
DB_USERNAME=postgres
DB_PASSWORD=secret
# 缓存与会话
CACHE_STORE=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=120
# 队列
QUEUE_CONNECTION=redis
# Redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
# 邮件(开发环境用 Mailpit 或 log)
MAIL_MAILER=log    # 开发环境:写日志而不是真发邮件
MAIL_FROM_ADDRESS="noreply@taskflow.app"
MAIL_FROM_NAME="${APP_NAME}"
# 文件存储
FILESYSTEM_DISK=local  # 开发用 local,生产用 s3
# 第三方服务
STRIPE_KEY=pk_test_xxx
STRIPE_SECRET=sk_test_xxx

多环境配置管理

# 不同环境有对应的 .env 文件(约定)
.env                 # 开发默认
.env.testing         # 测试环境(PHPUnit / Pest 自动使用)
.env.example         # 提交到 Git 的模板(不含真实值)
# .env.testing 示例:
APP_ENV=testing
DB_DATABASE=taskflow_test    # 独立的测试数据库
CACHE_STORE=array            # 测试用内存缓存,不依赖 Redis
QUEUE_CONNECTION=sync        # 测试用同步队列(立即执行,不需要 worker)
MAIL_MAILER=array            # 测试用内存邮件,不真实发送

自定义 config/ 文件

// config/taskflow.php(添加项目专属配置)
return [
'features' => [
'teams'    => env('FEATURE_TEAMS', false),
'billing'  => env('FEATURE_BILLING', true),
],
'limits' => [
'tasks_per_user'   => env('MAX_TASKS_PER_USER', 1000),
'file_upload_mb'   => env('MAX_FILE_UPLOAD_MB', 10),
],
'trial_days' => 14,
];
// 读取:
config('taskflow.features.teams')    // false
config('taskflow.limits.tasks_per_user')  // 1000
config('taskflow.trial_days')        // 14

配置缓存命令

# 生产环境:缓存配置(合并所有 config/*.php 到单文件,加速启动)
php artisan config:cache
# 开发环境:清除缓存(修改 .env 后必须执行)
php artisan config:clear
# 查看某个配置值(调试用)
php artisan tinker
>>> config('database.default')
>>> config('app.debug')
# 查看所有配置(会很长)
php artisan config:show database

敏感配置的安全实践

# .gitignore(确保 .env 不提交到 Git)
.env
.env.*.local
storage/
# ✅ 只提交 .env.example(移除真实值)
cp .env .env.example
# 然后手动清空 .env.example 中的敏感值
# 生产环境配置管理方案:
# 方案一:服务器环境变量(Laravel Forge 支持在界面设置)
# 方案二:AWS SSM Parameter Store / Secrets Manager
# 方案三:HashiCorp Vault
# 方案四:`.env` 文件通过加密存储在 CI/CD
# Laravel 11.28+ 支持用 php artisan env:encrypt 加密 .env
php artisan env:encrypt              # 生成 .env.encrypted
php artisan env:decrypt --env=production  # 解密(需要 APP_KEY)

AppServiceProvider 中读取配置

// app/Providers/AppServiceProvider.php
public function boot(): void
{
// 根据环境切换行为
if (app()->isProduction()) {
\URL::forceScheme('https');
\Horizon::auth(fn($request) => $request->user()?->isAdmin());
}
// 按功能 Flag 注册服务
if (config('taskflow.features.billing')) {
$this->app->singleton(
\App\Contracts\BillingInterface::class,
\App\Services\StripeBillingService::class
);
}
}

常见配置问题速查

问题 原因 解决
env() 返回 null 执行了 config:cache 后读 env() config() 替换 env()
修改 .env 没生效 缓存未清除 php artisan config:clear
生产环境 APP_DEBUG=true 忘记修改 必须设为 false,否则泄露堆栈信息
Session/Cache 失效 Redis 连接配置错误 检查 REDIS_HOST、密码、端口

下一章路由、控制器与请求处理——Laravel 的路由系统比你想的强大:路由分组、命名路由、中间件链——这些设计决策直接影响应用的可维护性。