本文目录导读:

处理PHP项目的多环境配置差异,核心原则是配置与代码分离,以下是系统化的解决方案:
基础方案(适合中小项目)
环境变量方式(推荐)
// config.php
return [
'db' => [
'host' => getenv('DB_HOST') ?: 'localhost',
'name' => getenv('DB_NAME') ?: 'app_db',
'user' => getenv('DB_USER') ?: 'root',
'pass' => getenv('DB_PASS') ?: '',
],
'debug' => filter_var(getenv('APP_DEBUG') ?: false, FILTER_VALIDATE_BOOLEAN),
'cache' => getenv('CACHE_DRIVER') ?: 'file',
];
配置文件切换
// config/loader.php
class ConfigLoader {
private static $instance = null;
private $config = [];
public static function load() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance->config;
}
private function __construct() {
$env = getenv('APP_ENV') ?: 'development';
$baseConfig = require __DIR__ . '/default.php';
// 加载环境特定配置
$envFile = __DIR__ . '/' . $env . '.php';
if (file_exists($envFile)) {
$envConfig = require $envFile;
$this->config = array_merge($baseConfig, $envConfig);
} else {
$this->config = $baseConfig;
}
}
}
配置文件结构示例
环境配置文件分离
project/
├── config/
│ ├── default.php # 默认配置
│ ├── development.php # 开发环境
│ ├── staging.php # 预发布环境
│ ├── production.php # 生产环境
│ └── testing.php # 测试环境
├── .env.example # 环境变量示例
├── .env.development # 开发环境变量(不入库)
└── .env.production # 生产环境变量(不入库)
default.php 示例
<?php
return [
'app' => [
'name' => 'MyApp',
'timezone' => 'Asia/Shanghai',
'debug' => false,
'log_level' => 'info',
],
'db' => [
'host' => 'localhost',
'port' => 3306,
'database' => 'app',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
],
'cache' => [
'driver' => 'file',
'prefix' => 'app_',
'ttl' => 3600,
],
'mail' => [
'host' => '',
'port' => 25,
'username' => '',
'password' => '',
'encryption' => 'tls',
],
'api' => [
'base_url' => '/api/v1',
'timeout' => 30,
],
];
各环境差异配置
// development.php
<?php
return [
'app' => [
'debug' => true,
'log_level' => 'debug',
],
'db' => [
'database' => 'app_dev',
'username' => 'dev_user',
],
'cache' => [
'driver' => 'file', // 开发环境用文件缓存
],
'mail' => [
'host' => 'localhost',
],
'api' => [
'base_url' => 'http://dev-api.example.com',
],
];
// production.php
<?php
return [
'app' => [
'debug' => false,
'log_level' => 'error',
],
'db' => [
'database' => 'app_prod',
'username' => 'prod_user',
],
'cache' => [
'driver' => 'redis', // 生产环境用Redis
],
'mail' => [
'host' => 'smtp.example.com',
'encryption' => 'tls',
],
'api' => [
'base_url' => 'https://api.example.com',
],
];
高级解决方案
使用Dotenv库(vlucas/phpdotenv)
// bootstrap.php
use Dotenv\Dotenv;
$dotenv = Dotenv::createImmutable(__DIR__ . '/../');
$dotenv->load();
// 设置APP_ENV并加载对应的配置
$appEnv = $_ENV['APP_ENV'] ?? 'production';
$configFiles = [
__DIR__ . "/config/{$appEnv}.php",
__DIR__ . '/config/default.php',
];
配置合并策略
// ConfigService.php
class ConfigService {
public static function getConfig($env) {
// 加载基础配置
$base = require __DIR__ . '/config/default.php';
// 加载环境配置并合并(环境配置覆盖基础配置)
$envConfig = require __DIR__ . "/config/{$env}.php";
// 递归合并数组
return self::arrayDeepMerge($base, $envConfig);
}
private static function arrayDeepMerge($array1, $array2) {
$result = $array1;
foreach ($array2 as $key => $value) {
if (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
$result[$key] = self::arrayDeepMerge($result[$key], $value);
} else {
$result[$key] = $value;
}
}
return $result;
}
}
容器化配置管理
# docker-compose.yml
version: '3'
services:
app:
environment:
- APP_ENV=production
- DB_HOST=database
- DB_NAME=app_prod
- CACHE_DRIVER=redis
env_file:
- .env.production
安全最佳实践
.gitignore 配置
# .gitignore
.env
.env.*
!.env.example
config/*.local.php
敏感信息保护
// 不要将真实密码写入配置文件
// 使用环境变量或在部署平台(AWS, Heroku等)设置
$dbPassword = getenv('DB_PASSWORD');
// 或者使用加密配置
$encryptedConfig = openssl_decrypt(
$storedValue,
'aes-256-cbc',
$_SERVER['ENCRYPTION_KEY'],
0,
$iv
);
自动化部署集成
CI/CD 配置
# .gitlab-ci.yml
stages:
- test
- deploy
variable_files:
development:
- .env.development
production:
- .env.production
deploy:
script:
- cp .env.$APP_ENV .env
- php artisan config:cache
环境检测工具
// Env.php
class Env {
public static function get() {
$env = getenv('APP_ENV');
if (!$env) {
// 自动检测(示例)
if (strpos(gethostname(), 'prod') !== false) {
$env = 'production';
} elseif (strpos(gethostname(), 'test') !== false) {
$env = 'testing';
} else {
$env = 'development';
}
}
// 校验环境名称
$supported = ['development', 'staging', 'production', 'testing'];
if (!in_array($env, $supported)) {
throw new \Exception("Invalid environment: {$env}");
}
return $env;
}
}
配置检查清单
- ✅ 配置文件加入版本控制(不含敏感信息)
- ✅ 环境变量在部署平台管理(不含代码中)
- ✅ 提供
.env.example模板 - ✅ 配置缓存策略(生产环境)
- ✅ 错误日志级别区分环境
- ✅ 数据库连接池配置差异
- ✅ API 端点域名不同环境分离
- ✅ 调试模式在生产环境禁用
框架案例
Laravel
# Laravel 自动根据 .env 文件中的 APP_ENV 加载配置 # 配置缓存:生产环境优化 php artisan config:cache php artisan config:clear
Symfony
# Symfony 根据 ENV 变量自动加载不同环境配置文件
# config/packages/doctrine.yaml
doctrine:
dbal:
url: '%env(DATABASE_URL)%'
这种方案既保证了代码的可移植性,又使得不同环境之间的配置完全隔离,同时降低了误操作的风险,选择哪种方案取决于项目规模和团队需求,建议从简单的环境变量方案开始,逐步优化。