本文目录导读:

在PHP部署中,环境区分(开发、测试、生产)是一个核心问题,以下是几种主流且实践性强的方案,按推荐程度排序:
环境变量方案(最推荐)
使用 .env 文件 + getenv()
// .env 文件(不同环境使用不同文件) // .env.development APP_ENV=development APP_DEBUG=true DB_HOST=localhost DB_DATABASE=dev_db // .env.production APP_ENV=production APP_DEBUG=false DB_HOST=192.168.1.100 DB_DATABASE=prod_db
// 加载对应环境的 .env 文件
$envFile = '.env.' . (getenv('APP_ENV') ?: 'development');
if (file_exists($envFile)) {
$lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (strpos($line, '=') !== false) {
list($key, $value) = explode('=', $line, 2);
putenv("$key=$value");
}
}
}
// 使用配置
$dbHost = getenv('DB_HOST');
使用 Dotenv 库(推荐生产使用)
// 安装:composer require vlucas/phpdotenv use Dotenv\Dotenv; // 根据服务器环境变量加载对应文件 $appEnv = $_SERVER['APP_ENV'] ?? 'development'; $dotenv = Dotenv::create(__DIR__, ".env.$appEnv"); $dotenv->load();
服务器配置区分
Nginx 配置
# 开发环境
server {
server_name dev.example.com;
fastcgi_param APP_ENV development;
}
# 生产环境
server {
server_name example.com;
fastcgi_param APP_ENV production;
}
Apache 配置
SetEnv APP_ENV development # 或 SetEnvIf Host "dev\.example\.com" APP_ENV=development
基于主机名自动判断(简单场景)
class EnvironmentDetector {
public static function detect() {
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
// 规则化匹配
if (strpos($host, 'localhost') !== false || strpos($host, '127.0.0.1') !== false) {
return 'development';
}
if (strpos($host, 'staging.') === 0) {
return 'staging';
}
if (strpos($host, 'dev.') === 0) {
return 'development';
}
return 'production';
}
}
$environment = EnvironmentDetector::detect();
配置文件分层方案
// config/base.php - 公共配置
return [
'app_name' => 'My App',
'timezone' => 'Asia/Shanghai',
];
// config/development.php
return [
'debug' => true,
'log_level' => 'debug',
'database' => [
'host' => 'localhost',
'database' => 'dev_db',
],
];
// config/production.php
return [
'debug' => false,
'log_level' => 'error',
'database' => [
'host' => 'production-db.example.com',
'database' => 'prod_db',
],
];
// 配置加载器
class ConfigLoader {
public static function load($environment) {
$base = require __DIR__ . '/config/base.php';
$envConfig = __DIR__ . '/config/' . $environment . '.php';
if (file_exists($envConfig)) {
return array_merge($base, require $envConfig);
}
return $base;
}
}
完整实践案例(推荐生产架构)
<?php
// bootstrap.php
class Environment {
private static $instance = null;
private $config = [];
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->detectEnvironment();
$this->loadConfiguration();
}
private function detectEnvironment() {
// 优先级:服务器变量 > 环境变量 > 域名判断
$this->environment = getenv('APP_ENV')
?: $_SERVER['APP_ENV']
?: $this->detectByHost()
?: 'production';
}
private function detectByHost() {
$host = $_SERVER['HTTP_HOST'] ?? '';
if (strpos($host, 'localhost') !== false) {
return 'development';
}
if (strpos($host, 'staging') !== false) {
return 'staging';
}
return null;
}
private function loadConfiguration() {
$configDir = __DIR__ . '/config/';
// 加载全局配置
$globalConfig = require $configDir . 'global.php';
// 加载环境特定配置
$envFile = $configDir . $this->environment . '.php';
if (file_exists($envFile)) {
$envConfig = require $envFile;
} else {
$envConfig = [];
}
$this->config = array_merge($globalConfig, $envConfig);
}
public function get($key = null) {
if ($key === null) {
return $this->config;
}
return $this->config[$key] ?? null;
}
public function isProduction() {
return $this->environment === 'production';
}
public function isDebug() {
return $this->config['debug'] ?? false;
}
}
部署时的自动化切换
# deploy.yml (部署工具配置示例)
environments:
development:
server: dev-server
env_file: .env.development
php_version: 7.4
staging:
server: staging-server
env_file: .env.staging
php_version: 8.0
production:
server:
- web1.example.com
- web2.example.com
env_file: .env.production
php_version: 8.1
optimize: true
# 部署脚本示例
#!/bin/bash
ENVIRONMENT=$1
case $ENVIRONMENT in
development)
cp .env.development .env
php artisan config:cache
;;
staging)
cp .env.staging .env
php artisan config:cache
php artisan migrate --force
;;
production)
cp .env.production .env
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan migrate --force
;;
esac
最佳实践建议
- 敏感信息不提交到代码库:将
.env.production加入.gitignore - 配置优先级:环境变量 > 配置文件 > 代码默认值
- 日志分级:根据环境调整日志级别
- 错误处理:生产环境隐藏错误详情,开发环境显示
- 自动检测+手动覆盖:多策略综合判断
选择哪种方案取决于项目复杂度,小型项目用简单的域名判断即可,大型项目建议使用环境变量 + 配置文件分层方案。