PHP项目环境与配置管理

wen PHP项目 1

本文目录导读:

PHP项目环境与配置管理

  1. 开发环境配置
  2. PHP配置管理
  3. .env文件管理
  4. 不同环境配置示例
  5. Docker 环境管理
  6. 配置文件加密
  7. 最佳实践
  8. 监控与调试

我来详细介绍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项目环境与配置管理的核心内容,涵盖了开发、测试和生产环境的完整配置方案,根据项目规模和需求,可以选择适合的方案组合使用。

抱歉,评论功能暂时关闭!