本文目录导读:

我来详细介绍PHP项目的环境与配置管理。
开发环境配置
1 PHP版本管理
# 使用 phpenv 管理多版本PHP phpenv install 8.2.0 phpenv global 8.2.0 phpenv local 7.4.33 # 或使用 Docker 容器化开发环境 docker run --name php-dev -d \ -v "$PWD":/var/www/html \ -p 8080:80 \ php:8.2-apache
2 环境配置文件结构
project/
├── .env # 环境变量
├── .env.example # 环境变量模板
├── .env.production # 生产环境配置
├── .env.staging # 预发布环境配置
├── config/
│ ├── app.php # 应用配置
│ ├── database.php # 数据库配置
│ ├── redis.php # Redis配置
│ └── mail.php # 邮件配置
└── docker/
├── Dockerfile
├── docker-compose.yml
└── nginx/
└── default.conf
PHP配置管理
1 php.ini 关键配置
; 生产环境推荐配置 [PHP] error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT display_errors = Off log_errors = On error_log = /var/log/php_errors.log ; 性能优化 max_execution_time = 30 memory_limit = 256M upload_max_filesize = 64M post_max_size = 80M ; OPcache opcache.enable = 1 opcache.memory_consumption = 128 opcache.interned_strings_buffer = 8 opcache.max_accelerated_files = 10000 opcache.revalidate_freq = 2
2 环境感知配置加载
<?php
// config/bootstrap.php
class EnvironmentConfig
{
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->loadEnvironment();
$this->loadConfigFiles();
}
private function loadEnvironment()
{
// 自动检测环境
$hostname = gethostname();
if (strpos($hostname, 'production') !== false) {
$this->environment = 'production';
} elseif (strpos($hostname, 'staging') !== false) {
$this->environment = 'staging';
} else {
$this->environment = 'development';
}
// 或通过环境变量设置
$this->environment = getenv('APP_ENV') ?: 'production';
}
private function loadConfigFiles()
{
$baseConfig = require __DIR__ . '/config/app.php';
$envConfig = require __DIR__ . "/config/{$this->environment}.php";
$this->config = array_merge($baseConfig, $envConfig);
}
public function get($key, $default = null)
{
return $this->config[$key] ?? $default;
}
}
.env文件管理
1 PHP dotenv 实现
<?php
// src/Dotenv.php
class Dotenv
{
protected $path;
protected $loaded = false;
public function __construct($path)
{
$this->path = $path;
}
public function load()
{
if ($this->loaded) {
return;
}
$filePath = $this->path . '/.env';
if (!file_exists($filePath)) {
throw new \RuntimeException('.env file not found');
}
$lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (strpos(trim($line), '#') === 0) {
continue; // 跳过注释
}
list($name, $value) = explode('=', $line, 2);
$name = trim($name);
$value = trim($value);
// 处理引号
if (preg_match('/^"(.*)"$/', $value, $matches)) {
$value = $matches[1];
} elseif (preg_match("/^'(.*)'$/", $value, $matches)) {
$value = $matches[1];
}
// 处理变量替换
$value = preg_replace_callback('/\${([^}]+)}/', function($matches) {
return getenv($matches[1]) ?: '';
}, $value);
putenv("{$name}={$value}");
$_ENV[$name] = $value;
}
$this->loaded = true;
}
}
2 .env.example 模板
# .env.example APP_ENV=development APP_DEBUG=true APP_URL=http://localhost:8080 DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=app_name DB_USERNAME=root DB_PASSWORD= REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_DRIVER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null
不同环境配置示例
1 开发环境 (config/development.php)
<?php
return [
'debug' => true,
'log_level' => 'debug',
'cache_driver' => 'file',
'session_handler' => 'file',
'database' => [
'host' => 'localhost',
'port' => 3306,
'database' => 'app_dev',
'username' => 'root',
'password' => 'root',
'charset' => 'utf8mb4',
],
'mail' => [
'driver' => 'log', // 只记录日志,不真正发送
'from' => ['address' => 'dev@example.com', 'name' => 'Dev App'],
],
'services' => [
'api_base_url' => 'http://api.dev.example.com',
'debug_mode' => true,
],
];
2 生产环境 (config/production.php)
<?php
return [
'debug' => false,
'log_level' => 'error',
'cache_driver' => 'redis',
'session_handler' => 'redis',
'database' => [
'host' => getenv('DB_HOST') ?: 'localhost',
'port' => getenv('DB_PORT') ?: 3306,
'database' => getenv('DB_DATABASE'),
'username' => getenv('DB_USERNAME'),
'password' => getenv('DB_PASSWORD'),
'charset' => 'utf8mb4',
'pool' => [
'min_connections' => 5,
'max_connections' => 100,
],
],
'mail' => [
'driver' => 'smtp',
'host' => getenv('MAIL_HOST'),
'port' => getenv('MAIL_PORT'),
'encryption' => 'tls',
],
'cache' => [
'driver' => 'redis',
'prefix' => 'prod_',
'ttl' => 3600,
],
];
Docker 环境管理
1 docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: php-app
restart: unless-stopped
working_dir: /var/www
volumes:
- ./:/var/www
- ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
environment:
- APP_ENV=${APP_ENV}
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
- db
- redis
networks:
- app-network
db:
image: mysql:8.0
container_name: mysql-db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
ports:
- "3306:3306"
volumes:
- dbdata:/var/lib/mysql
networks:
- app-network
redis:
image: redis:alpine
container_name: redis-cache
restart: unless-stopped
ports:
- "6379:6379"
volumes:
- redisdata:/data
networks:
- app-network
nginx:
image: nginx:alpine
container_name: nginx-server
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www
- ./docker/nginx/conf.d:/etc/nginx/conf.d
depends_on:
- app
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
dbdata:
redisdata:
2 Dockerfile
FROM php:8.2-fpm
# 安装系统依赖
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
libzip-dev \
unzip \
libpq-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# 安装PHP扩展
RUN docker-php-ext-install \
pdo_mysql \
pdo_pgsql \
mbstring \
exif \
pcntl \
bcmath \
gd \
zip
# 安装Redis扩展
RUN pecl install redis && docker-php-ext-enable redis
# 安装Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# 设置工作目录
WORKDIR /var/www
# 复制配置文件
COPY docker/php/php.ini /usr/local/etc/php/php.ini
COPY docker/php/php-fpm.conf /usr/local/etc/php-fpm.d/www.conf
# 创建用户
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www
# 设置权限
COPY --chown=www:www . /var/www
# 切换用户
USER www
EXPOSE 9000
CMD ["php-fpm"]
配置文件加密
1 敏感信息加密
<?php
// src/EncryptedConfig.php
class EncryptedConfig
{
private $encryptionKey;
private $config;
public function __construct($encryptionKey)
{
$this->encryptionKey = $encryptionKey;
}
public function decryptConfig($encryptedConfig)
{
$decrypted = [];
foreach ($encryptedConfig as $key => $value) {
if ($this->isEncrypted($value)) {
$decrypted[$key] = $this->decrypt($value);
} else {
$decrypted[$key] = $value;
}
}
return $decrypted;
}
private function decrypt($encryptedValue)
{
$cipher = "AES-256-CBC";
$data = base64_decode($encryptedValue);
$ivLength = openssl_cipher_iv_length($cipher);
$iv = substr($data, 0, $ivLength);
$encrypted = substr($data, $ivLength);
return openssl_decrypt($encrypted, $cipher, $this->encryptionKey, 0, $iv);
}
private function isEncrypted($value)
{
return preg_match('/^ENC\[/', $value) === 1;
}
}
2 配置文件加密工具
<?php
// bin/encrypt-config.php
class ConfigEncryptor
{
public function encryptConfig($config, $key)
{
$encrypted = [];
foreach ($config as $key => $value) {
$encrypted[$key] = $this->encrypt($value, $key);
}
return $encrypted;
}
private function encrypt($value, $key)
{
$cipher = "AES-256-CBC";
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));
$encrypted = openssl_encrypt($value, $cipher, $key, 0, $iv);
return 'ENC[' . base64_encode($iv . $encrypted) . ']';
}
public function saveEncryptedConfig($config, $outputFile, $key)
{
$encryptedConfig = $this->encryptConfig($config, $key);
file_put_contents(
$outputFile,
'<?php return ' . var_export($encryptedConfig, true) . ';'
);
}
}
最佳实践
1 配置管理规范
<?php
// config/config-manager.php
class ConfigManager
{
private $loaded = [];
private $cache = [];
/**
* 安全获取配置
*/
public function get($key, $default = null)
{
if (isset($this->cache[$key])) {
return $this->cache[$key];
}
$value = $this->getConfigValue($key, $default);
// 缓存配置
$this->cache[$key] = $value;
return $value;
}
/**
* 验证配置完整性
*/
public function validateConfig()
{
$required = [
'DB_HOST',
'DB_DATABASE',
'APP_KEY',
'APP_ENV',
];
$missing = [];
foreach ($required as $key) {
if ($this->get($key) === null) {
$missing[] = $key;
}
}
if (!empty($missing)) {
throw new \RuntimeException(
'Missing required config: ' . implode(', ', $missing)
);
}
return true;
}
/**
* 环境特定配置覆盖
*/
public function overrideConfig($environment)
{
$overrides = $this->loadEnvironmentConfig($environment);
foreach ($overrides as $key => $value) {
if ($this->has($key)) {
$this->cache[$key] = $value;
}
}
}
}
2 CI/CD 配置管理
# .gitlab-ci.yml
stages:
- test
- deploy
variables:
APP_ENV: $CI_ENVIRONMENT_NAME
before_script:
- cp .env.$CI_ENVIRONMENT_NAME .env
- composer install --no-interaction
test:
stage: test
script:
- php artisan config:cache
- php artisan test
only:
- develop
- master
deploy_production:
stage: deploy
environment:
name: production
script:
- php artisan config:clear
- php artisan config:cache
- php artisan migrate --force
only:
- master
when: manual
监控与调试
1 配置验证检查
<?php
// console/check-config.php
class ConfigCheckCommand
{
public function execute()
{
$checks = [
'PHP Version' => PHP_VERSION >= '8.0',
'PDO Extension' => extension_loaded('pdo'),
'OpenSSL Extension' => extension_loaded('openssl'),
'File Permissions' => is_writable(storage_path()),
'Environment File' => file_exists('.env'),
];
$failed = false;
foreach ($checks as $check => $result) {
if ($result) {
echo "✓ {$check}: Passed\n";
} else {
echo "✗ {$check}: Failed\n";
$failed = true;
}
}
return $failed ? 1 : 0;
}
}
这些是PHP项目环境与配置管理的核心内容,涵盖了开发、测试和生产环境的完整配置方案,根据项目规模和需求,可以选择适合的方案组合使用。