首页 / 教程文章 / WordPress柔性供应链软件开发中的持续集成与部署教程

WordPress柔性供应链软件开发中的持续集成与部署教程

WordPress柔性供应链软件开发中的持续集成与部署教程

引言:柔性供应链与WordPress开发的结合

在当今快速变化的商业环境中,柔性供应链系统已成为企业保持竞争力的关键。将这种灵活性融入WordPress开发中,可以创建出既能适应需求波动又能保持稳定性的供应链解决方案。然而,随着系统复杂性的增加,如何确保代码质量和部署效率成为开发团队面临的重要挑战。持续集成与部署(CI/CD)正是解决这一问题的有效方法。

本文将详细介绍在WordPress柔性供应链软件开发中实施CI/CD的完整流程,包括环境配置、自动化测试、部署策略等关键环节,并提供可直接使用的代码示例。

环境配置与基础架构

1.1 版本控制系统设置

首先,我们需要建立代码版本控制系统。Git是目前最流行的选择,配合GitHub、GitLab或Bitbucket等平台使用。

# 初始化Git仓库
git init

# 添加远程仓库
git remote add origin https://github.com/your-username/wordpress-supply-chain.git

# 创建基础分支结构
git checkout -b main
git checkout -b develop
git checkout -b feature/supply-chain-module

# 创建.gitignore文件,排除不需要版本控制的文件
echo "# WordPress核心文件(不应包含在仓库中)
wordpress/
wp-config.php

# 依赖文件
node_modules/
vendor/

# 环境配置文件
.env
.env.local

# 系统文件
.DS_Store
Thumbs.db

# IDE文件
.idea/
.vscode/
*.swp

# 日志文件
*.log" > .gitignore

1.2 Docker容器化配置

使用Docker可以确保开发、测试和生产环境的一致性。以下是Docker配置示例:

# Dockerfile - WordPress柔性供应链应用
FROM wordpress:php8.0-apache

# 设置工作目录
WORKDIR /var/www/html

# 安装系统依赖
RUN apt-get update && apt-get install -y 
    git 
    unzip 
    curl 
    libzip-dev 
    libpng-dev 
    libjpeg-dev 
    libfreetype6-dev 
    && docker-php-ext-configure gd --with-freetype --with-jpeg 
    && docker-php-ext-install -j$(nproc) gd zip pdo_mysql

# 安装Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# 复制自定义代码
COPY wp-content/plugins/supply-chain /var/www/html/wp-content/plugins/supply-chain
COPY wp-content/themes/supply-chain-theme /var/www/html/wp-content/themes/supply-chain-theme

# 设置权限
RUN chown -R www-data:www-data /var/www/html 
    && chmod -R 755 /var/www/html/wp-content

# 暴露端口
EXPOSE 80

# 启动Apache
CMD ["apache2-foreground"]
# docker-compose.yml - 多容器环境配置
version: '3.8'

services:
  db:
    image: mysql:8.0
    container_name: wp_supply_chain_db
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - wordpress-network

  wordpress:
    build: .
    container_name: wp_supply_chain
    restart: always
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: ${DB_USER}
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
      WORDPRESS_DB_NAME: ${DB_NAME}
    volumes:
      - wordpress_data:/var/www/html/wp-content
      - ./custom-plugins:/var/www/html/wp-content/plugins/custom
    depends_on:
      - db
    networks:
      - wordpress-network

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: wp_supply_chain_pma
    restart: always
    ports:
      - "8081:80"
    environment:
      PMA_HOST: db
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    networks:
      - wordpress-network

networks:
  wordpress-network:
    driver: bridge

volumes:
  db_data:
  wordpress_data:

持续集成流水线配置

2.1 GitHub Actions工作流配置

GitHub Actions提供了强大的CI/CD功能。以下是一个完整的WordPress插件测试工作流:

# .github/workflows/ci-cd.yml
name: WordPress供应链插件CI/CD

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  # 代码质量检查
  code-quality:
    runs-on: ubuntu-latest
    
    steps:
    - name: 检出代码
      uses: actions/checkout@v3
      
    - name: 设置PHP环境
      uses: shivammathur/setup-php@v2
      with:
        php-version: '8.0'
        extensions: mbstring, xml, ctype, iconv, intl, pdo_mysql
        coverage: xdebug
        
    - name: 验证Composer配置
      run: composer validate --strict
      
    - name: 安装依赖
      run: composer install --prefer-dist --no-progress
      
    - name: PHP代码风格检查
      run: composer run phpcs
      
    - name: 静态分析
      run: composer run phpstan
      
    - name: 安全漏洞扫描
      run: composer run security-check

  # 单元测试与集成测试
  test:
    runs-on: ubuntu-latest
    needs: code-quality
    
    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: wordpress_test
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
    
    steps:
    - name: 检出代码
      uses: actions/checkout@v3
      
    - name: 设置PHP环境
      uses: shivammathur/setup-php@v2
      with:
        php-version: '8.0'
        extensions: mbstring, xml, ctype, iconv, intl, pdo_mysql
        coverage: xdebug
        
    - name: 安装WordPress测试框架
      run: |
        bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 latest true
        
    - name: 运行单元测试
      run: composer run test-unit
      env:
        WP_TESTS_DIR: /tmp/wordpress-tests-lib
        
    - name: 运行集成测试
      run: composer run test-integration
      
    - name: 生成测试覆盖率报告
      run: composer run test-coverage
      
    - name: 上传测试结果
      uses: actions/upload-artifact@v3
      with:
        name: test-results
        path: tests/_output/

  # 构建与部署
  deploy:
    runs-on: ubuntu-latest
    needs: test
    if: github.ref == 'refs/heads/main'
    
    steps:
    - name: 检出代码
      uses: actions/checkout@v3
      
    - name: 设置部署环境变量
      run: |
        echo "DEPLOY_TIME=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
        
    - name: 构建Docker镜像
      run: |
        docker build -t supply-chain-plugin:latest .
        docker tag supply-chain-plugin:latest your-registry/supply-chain-plugin:${{ env.DEPLOY_TIME }}
        
    - name: 推送Docker镜像
      run: |
        echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
        docker push your-registry/supply-chain-plugin:${{ env.DEPLOY_TIME }}
        
    - name: 部署到生产环境
      run: |
        # 使用SSH连接到生产服务器并部署
        echo "${{ secrets.SSH_PRIVATE_KEY }}" > private_key
        chmod 600 private_key
        ssh -o StrictHostKeyChecking=no -i private_key 
          ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} 
          "cd /var/www/supply-chain && ./deploy.sh ${{ env.DEPLOY_TIME }}"

2.2 WordPress插件自动化测试示例

以下是一个供应链管理插件的测试示例:

<?php
/**
 * 供应链库存管理测试类
 * 
 * @package SupplyChainTests
 */

use PHPUnitFrameworkTestCase;

/**
 * 库存管理测试类
 */
class InventoryManagerTest extends TestCase
{
    /**
     * 测试库存初始化
     */
    public function testInventoryInitialization()
    {
        $inventory = new InventoryManager();
        
        // 测试空库存
        $this->assertEquals(0, $inventory->getTotalItems());
        
        // 添加测试产品
        $product = [
            'id' => 1,
            'name' => '测试产品',
            'sku' => 'TEST-001',
            'quantity' => 100,
            'reorder_level' => 20
        ];
        
        $result = $inventory->addProduct($product);
        $this->assertTrue($result);
        $this->assertEquals(1, $inventory->getTotalItems());
        $this->assertEquals(100, $inventory->getProductQuantity(1));
    }
    
    /**
     * 测试库存更新
     */
    public function testInventoryUpdate()
    {
        $inventory = new InventoryManager();
        
        // 初始化库存
        $inventory->addProduct([
            'id' => 1,
            'name' => '测试产品',
            'sku' => 'TEST-001',
            'quantity' => 50,
            'reorder_level' => 10
        ]);
        
        // 测试增加库存
        $inventory->updateQuantity(1, 25);
        $this->assertEquals(75, $inventory->getProductQuantity(1));
        
        // 测试减少库存
        $inventory->updateQuantity(1, -30);
        $this->assertEquals(45, $inventory->getProductQuantity(1));
        
        // 测试库存不足
        $this->expectException(InsufficientInventoryException::class);
        $inventory->updateQuantity(1, -100);
    }
    
    /**
     * 测试重新订购逻辑
     */
    public function testReorderLogic()
    {
        $inventory = new InventoryManager();
        
        // 添加低于重新订购水平的产品
        $inventory->addProduct([
            'id' => 1,
            'name' => '测试产品',
            'sku' => 'TEST-001',
            'quantity' => 5,
            'reorder_level' => 10,
            'reorder_quantity' => 50
        ]);
        
        // 检查是否需要重新订购
        $productsToReorder = $inventory->getProductsNeedingReorder();
        $this->assertCount(1, $productsToReorder);
        $this->assertEquals(1, $productsToReorder[0]['product_id']);
        
        // 执行重新订购
        $orderId = $inventory->processReorder(1);
        $this->assertIsInt($orderId);
        $this->assertGreaterThan(0, $orderId);
        
        // 验证库存已更新
        $this->assertEquals(55, $inventory->getProductQuantity(1));
    }
}

/**
 * 库存管理类
 */
class InventoryManager
{
    private $inventory = [];
    
    /**
     * 添加产品到库存
     * 
     * @param array $product 产品数据
     * @return bool 添加是否成功
     */
    public function addProduct(array $product): bool
    {
        // 验证必需字段
        $requiredFields = ['id', 'name', 'sku', 'quantity'];
        foreach ($requiredFields as $field) {
            if (!isset($product[$field])) {
                throw new InvalidArgumentException("缺少必需字段: {$field}");
            }
        }
        
        $this->inventory[$product['id']] = [
            'id' => $product['id'],
            'name' => $product['name'],
            'sku' => $product['sku'],
            'quantity' => (int)$product['quantity'],
            'reorder_level' => $product['reorder_level'] ?? 0,
            'reorder_quantity' => $product['reorder_quantity'] ?? 0
        ];
        
        return true;
    }
    
    /**
     * 获取产品数量
     * 
     * @param int $productId 产品ID
     * @return int 产品数量
     */
    public function getProductQuantity(int $productId): int
    {
        if (!isset($this->inventory[$productId])) {
            throw new InvalidArgumentException("产品不存在: {$productId}");
        }
        
        return $this->inventory[$productId]['quantity'];
    }
    
    /**
     * 更新产品数量
     * 
     * @param int $productId 产品ID
     * @param int $delta 数量变化(正数增加,负数减少)
     * @return bool 更新是否成功
     */
    public function updateQuantity(int $productId, int $delta): bool
    {
        if (!isset($this->inventory[$productId])) {
            throw new InvalidArgumentException("产品不存在: {$productId}");
        }
        
        $newQuantity = $this->inventory[$productId]['quantity'] + $delta;
        
        if ($newQuantity < 0) {
            throw new InsufficientInventoryException(
                "库存不足。产品ID: {$productId}, 当前库存: {$this->inventory[$productId]['quantity']}, 需求: " . abs($delta)
            );
        }
        
        $this->inventory[$productId]['quantity'] = $newQuantity;
        return true;
    }
    
    /**
     * 获取需要重新订购的产品
     * 
     * @return array 需要重新订购的产品列表
     */
    public function getProductsNeedingReorder(): array
    {
        $products = [];
        
        foreach ($this->inventory as $product) {
            if ($product['reorder_level'] > 0 && 
                $product['quantity'] <= $product['reorder_level'] &&
                $product['reorder_quantity'] > 0) {
                $products[] = [
                    'product_id' => $product['id'],
                    'product_name' => $product['name'],
                    'current_quantity' => $product['quantity'],
                    'reorder_level' => $product['reorder_level'],
                    'reorder_quantity' => $product['reorder_quantity']
                ];
            }
        }
        
        return $products;
    }
    
    /**
     * 获取总产品数量
     * 
     * @return int 总产品数量
     */
    public function getTotalItems(): int
    {
        return count($this->inventory);
    }
}

/**
 * 库存不足异常类
 */
class InsufficientInventoryException extends Exception
{
    // 自定义异常类
}
?>

自动化部署策略

3.1 蓝绿部署配置

蓝绿部署可以最小化部署风险,确保供应链系统的持续可用性。

#!/bin/bash
# deploy.sh - 蓝绿部署脚本

set -e

DEPLOY_VERSION=$1
BLUE_DIR="/var/www/supply-chain-blue"
GREEN_DIR="/var/www/supply-chain-green"
CURRENT_LINK="/var/www/supply-chain-current"
NGINX_CONFIG="/etc/nginx/sites-available/supply-chain"

# 检查当前活动环境
if [ -L "$CURRENT_LINK" ]; then
    CURRENT_ENV=$(readlink -f "$CURRENT_LINK")
    if [[ "$CURRENT_ENV" == *"-blue" ]]; then
        ACTIVE="blue"
        STANDBY="green"
        STANDBY_DIR="$GREEN_DIR"
    else
        ACTIVE="green"
        STANDBY="blue"
        STANDBY_DIR="$BLUE_DIR"
    fi
else
    # 首次部署
    ACTIVE="blue"
    STANDBY="green"
    STANDBY_DIR="$GREEN_DIR"
fi

echo "当前活动环境: $ACTIVE"
echo "准备部署到备用环境: $STANDBY"

# 准备备用环境目录
if [ ! -d "$STANDBY_DIR" ]; then
    mkdir -p "$STANDBY_DIR"
fi

# 拉取新版本Docker镜像
echo "拉取版本 $DEPLOY_VERSION 的Docker镜像..."
docker pull your-registry/supply-chain-plugin:$DEPLOY_VERSION

# 停止备用环境容器
cd "$STANDBY_DIR"
docker-compose down || true

# 更新环境变量
echo "DEPLOY_VERSION=$DEPLOY_VERSION" > .env
echo "DB_HOST=supply-chain-db" >> .env
echo "DB_NAME=supply_chain_$STANDBY" >> .env

# 启动备用环境
docker-compose up -d

# 等待服务就绪
echo "等待 $STANDBY 环境就绪..."
for i in {1..30}; do
    if curl -f http://localhost:8080/health-check > /dev/null 2>&1; then
        echo "$STANDBY 环境已就绪"
        break
    fi
    sleep 2
done

# 运行数据库迁移
echo "运行数据库迁移..."
docker-compose exec -T wordpress php wp-content/plugins/supply-chain/migrations/migrate.php

# 运行健康检查
echo "运行健康检查..."
HEALTH_CHECK_RESULT=$(docker-compose exec -T wordpress curl -s http://localhost/health-check)

自动化部署策略(续)

3.1 蓝绿部署配置(续)

    echo "健康检查失败: $HEALTH_CHECK_RESULT"
    exit 1
fi

# 切换流量到新环境
echo "切换流量到 $STANDBY 环境..."
ln -sfn "$STANDBY_DIR" "$CURRENT_LINK"

# 重新加载Nginx配置
nginx -s reload

echo "流量切换完成,新环境已激活"

# 运行自动化测试验证新环境
echo "运行自动化测试验证新环境..."
docker-compose exec -T wordpress php vendor/bin/phpunit 
    --testsuite production 
    --configuration phpunit.production.xml

# 清理旧环境(可选,保留一段时间用于回滚)
echo "清理旧环境..."
OLD_ENV_DIR=$([ "$STANDBY" = "blue" ] && echo "$GREEN_DIR" || echo "$BLUE_DIR")
cd "$OLD_ENV_DIR"
docker-compose down

echo "部署完成!版本 $DEPLOY_VERSION 已成功上线"

3.2 数据库迁移管理

在供应链系统中,数据库结构可能频繁变更。以下是数据库迁移管理脚本:

<?php
/**
 * 供应链数据库迁移管理器
 * 
 * @package SupplyChainMigrations
 */

class MigrationManager
{
    private $wpdb;
    private $migrations_table = 'supply_chain_migrations';
    
    public function __construct()
    {
        global $wpdb;
        $this->wpdb = $wpdb;
        $this->createMigrationsTable();
    }
    
    /**
     * 创建迁移记录表
     */
    private function createMigrationsTable()
    {
        $charset_collate = $this->wpdb->get_charset_collate();
        
        $sql = "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}{$this->migrations_table} (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            migration_name varchar(255) NOT NULL,
            batch int(11) NOT NULL,
            applied_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            UNIQUE KEY migration_name (migration_name)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
    }
    
    /**
     * 运行所有待处理的迁移
     */
    public function runMigrations()
    {
        $applied_migrations = $this->getAppliedMigrations();
        $migration_files = $this->getMigrationFiles();
        
        $new_migrations = array_diff($migration_files, $applied_migrations);
        
        if (empty($new_migrations)) {
            return ['success' => true, 'message' => '没有需要运行的迁移'];
        }
        
        sort($new_migrations);
        $batch = $this->getNextBatchNumber();
        
        foreach ($new_migrations as $migration) {
            try {
                $this->runMigration($migration, $batch);
                error_log("迁移成功: $migration");
            } catch (Exception $e) {
                error_log("迁移失败: $migration - " . $e->getMessage());
                return ['success' => false, 'message' => "迁移失败: $migration"];
            }
        }
        
        return ['success' => true, 'message' => '所有迁移已成功运行'];
    }
    
    /**
     * 运行单个迁移
     */
    private function runMigration($migration_name, $batch)
    {
        $migration_file = SUPPLY_CHAIN_PLUGIN_DIR . "/migrations/{$migration_name}.php";
        
        if (!file_exists($migration_file)) {
            throw new Exception("迁移文件不存在: {$migration_file}");
        }
        
        require_once($migration_file);
        
        $class_name = $this->getClassNameFromFileName($migration_name);
        
        if (!class_exists($class_name)) {
            throw new Exception("迁移类不存在: {$class_name}");
        }
        
        $migration = new $class_name($this->wpdb);
        
        // 开始事务
        $this->wpdb->query('START TRANSACTION');
        
        try {
            $migration->up();
            
            // 记录迁移
            $this->wpdb->insert(
                $this->wpdb->prefix . $this->migrations_table,
                [
                    'migration_name' => $migration_name,
                    'batch' => $batch
                ]
            );
            
            $this->wpdb->query('COMMIT');
        } catch (Exception $e) {
            $this->wpdb->query('ROLLBACK');
            throw $e;
        }
    }
    
    /**
     * 回滚迁移
     */
    public function rollback($steps = 1)
    {
        $last_batch = $this->getLastBatch();
        $migrations_to_rollback = $this->wpdb->get_results(
            $this->wpdb->prepare(
                "SELECT migration_name FROM {$this->wpdb->prefix}{$this->migrations_table} 
                 WHERE batch = %d ORDER BY id DESC",
                $last_batch
            )
        );
        
        if (empty($migrations_to_rollback)) {
            return ['success' => true, 'message' => '没有需要回滚的迁移'];
        }
        
        foreach ($migrations_to_rollback as $migration) {
            try {
                $this->rollbackMigration($migration->migration_name);
                error_log("回滚成功: {$migration->migration_name}");
            } catch (Exception $e) {
                error_log("回滚失败: {$migration->migration_name} - " . $e->getMessage());
                return ['success' => false, 'message' => "回滚失败: {$migration->migration_name}"];
            }
        }
        
        return ['success' => true, 'message' => '回滚完成'];
    }
    
    /**
     * 获取迁移文件列表
     */
    private function getMigrationFiles()
    {
        $files = glob(SUPPLY_CHAIN_PLUGIN_DIR . '/migrations/*.php');
        return array_map('basename', $files);
    }
    
    /**
     * 获取已应用的迁移
     */
    private function getAppliedMigrations()
    {
        $results = $this->wpdb->get_col(
            "SELECT migration_name FROM {$this->wpdb->prefix}{$this->migrations_table}"
        );
        return $results ?: [];
    }
}

/**
 * 示例迁移文件:创建库存表
 * 文件路径:migrations/2023_10_01_000001_create_inventory_table.php
 */
class CreateInventoryTable
{
    private $wpdb;
    
    public function __construct($wpdb)
    {
        $this->wpdb = $wpdb;
    }
    
    public function up()
    {
        $charset_collate = $this->wpdb->get_charset_collate();
        
        $sql = "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}supply_chain_inventory (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            product_id bigint(20) NOT NULL,
            sku varchar(100) NOT NULL,
            product_name varchar(255) NOT NULL,
            quantity int(11) NOT NULL DEFAULT 0,
            reorder_level int(11) NOT NULL DEFAULT 0,
            reorder_quantity int(11) NOT NULL DEFAULT 0,
            location varchar(100),
            last_updated datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            UNIQUE KEY sku (sku),
            KEY product_id (product_id),
            KEY location (location)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
        
        // 添加初始数据
        $this->wpdb->insert(
            $this->wpdb->prefix . 'supply_chain_inventory',
            [
                'product_id' => 1,
                'sku' => 'DEFAULT-001',
                'product_name' => '默认产品',
                'quantity' => 100,
                'reorder_level' => 20,
                'reorder_quantity' => 50,
                'location' => '主仓库'
            ]
        );
    }
    
    public function down()
    {
        $sql = "DROP TABLE IF EXISTS {$this->wpdb->prefix}supply_chain_inventory";
        $this->wpdb->query($sql);
    }
}
?>

监控与日志管理

4.1 应用性能监控配置

<?php
/**
 * 供应链系统监控配置
 * 
 * @package SupplyChainMonitoring
 */

class SupplyChainMonitor
{
    private $metrics = [];
    private $log_file;
    
    public function __construct()
    {
        $upload_dir = wp_upload_dir();
        $this->log_file = $upload_dir['basedir'] . '/supply-chain-logs/monitor.log';
        
        // 确保日志目录存在
        wp_mkdir_p(dirname($this->log_file));
        
        // 注册关闭函数,确保指标被记录
        register_shutdown_function([$this, 'logMetrics']);
    }
    
    /**
     * 记录性能指标
     */
    public function recordMetric($name, $value, $labels = [])
    {
        $this->metrics[] = [
            'timestamp' => microtime(true),
            'name' => $name,
            'value' => $value,
            'labels' => $labels
        ];
    }
    
    /**
     * 记录API响应时间
     */
    public function recordApiResponseTime($endpoint, $response_time)
    {
        $this->recordMetric('api_response_time', $response_time, [
            'endpoint' => $endpoint,
            'method' => $_SERVER['REQUEST_METHOD'] ?? 'CLI'
        ]);
    }
    
    /**
     * 记录数据库查询性能
     */
    public function recordQueryPerformance($query, $execution_time)
    {
        // 简化查询用于记录
        $simplified_query = preg_replace('/s+/', ' ', $query);
        $simplified_query = substr($simplified_query, 0, 200);
        
        $this->recordMetric('db_query_time', $execution_time, [
            'query_type' => $this->getQueryType($query),
            'query_hash' => md5($query)
        ]);
    }
    
    /**
     * 记录库存操作
     */
    public function recordInventoryOperation($operation, $product_id, $quantity, $success)
    {
        $this->recordMetric('inventory_operation', 1, [
            'operation' => $operation,
            'product_id' => $product_id,
            'quantity' => $quantity,
            'success' => $success ? 'true' : 'false'
        ]);
    }
    
    /**
     * 将指标记录到文件
     */
    public function logMetrics()
    {
        if (empty($this->metrics)) {
            return;
        }
        
        $log_data = [
            'timestamp' => date('Y-m-d H:i:s'),
            'metrics' => $this->metrics,
            'memory_usage' => memory_get_peak_usage(true) / 1024 / 1024, // MB
            'execution_time' => microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']
        ];
        
        $log_line = json_encode($log_data) . PHP_EOL;
        
        // 使用文件锁避免并发写入问题
        $fp = fopen($this->log_file, 'a');
        if (flock($fp, LOCK_EX)) {
            fwrite($fp, $log_line);
            flock($fp, LOCK_UN);
        }
        fclose($fp);
        
        // 发送到外部监控系统(可选)
        $this->sendToExternalMonitor($log_data);
    }
    
    /**
     * 发送指标到外部监控系统
     */
    private function sendToExternalMonitor($data)
    {
        // 发送到Prometheus Pushgateway
        if (defined('PROMETHEUS_PUSHGATEWAY_URL')) {
            $metrics = [];
            
            foreach ($data['metrics'] as $metric) {
                $metric_name = str_replace('.', '_', $metric['name']);
                $labels = '';
                
                if (!empty($metric['labels'])) {
                    $label_parts = [];
                    foreach ($metric['labels'] as $key => $value) {
                        $label_parts[] = $key . '="' . addslashes($value) . '"';
                    }
                    $labels = '{' . implode(',', $label_parts) . '}';
                }
                
                $metrics[] = "supply_chain_{$metric_name}{$labels} {$metric['value']}";
            }
            
            if (!empty($metrics)) {
                $ch = curl_init(PROMETHEUS_PUSHGATEWAY_URL);
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_POSTFIELDS, implode("n", $metrics));
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_exec($ch);
                curl_close($ch);
            }
        }
    }
    
    /**
     * 获取查询类型
     */
    private function getQueryType($query)
    {
        $query = strtoupper(trim($query));
        
        if (strpos($query, 'SELECT') === 0) return 'SELECT';
        if (strpos($query, 'INSERT') === 0) return 'INSERT';
        if (strpos($query, 'UPDATE') === 0) return 'UPDATE';
        if (strpos($query, 'DELETE') === 0) return 'DELETE';
        
        return 'OTHER';
    }
}

/**
 * 日志轮转管理
 */
class LogRotator
{
    public static function rotateLogs($log_dir, $max_files = 30, $max_size_mb = 100)
    {
        $files = glob($log_dir . '/*.log');
        
        foreach ($files as $file) {
            // 检查文件大小
            if (filesize($file) > $max_size_mb * 1024 * 1024) {
                self::rotateSingleFile($file, $max_files);
            }
        }
    }
    
    private static function rotateSingleFile($file, $max_files)
    {
        // 压缩并重命名当前日志文件
        $timestamp = date('Ymd_His');
        $rotated_file = $file . '.' . $timestamp . '.gz';
        
        // 压缩文件
        $fp = gzopen($rotated_file, 'w9');
        if ($fp) {
            gzwrite($fp, file_get_contents($file));
            gzclose($fp);
            
            // 清空原文件
            file_put_contents($file, '');
            
            // 清理旧日志文件
            self::cleanupOldFiles(dirname($file), $max_files);
        }
    }
    
    private static function cleanupOldFiles($log_dir, $max_files)
    {
        $files = glob($log_dir . '/*.gz');
        
        // 按修改时间排序
        usort($files, function($a, $b) {
            return filemtime($b) - filemtime($a);
        });
        
        // 删除超出数量限制的文件
        if (count($files) > $max_files) {
            $files_to_delete = array_slice($files, $max_files);
            foreach ($files_to_delete as $file) {
                unlink($file);
            }
        }
    }
}
?>

安全与合规性检查

5.1 自动化安全扫描

# .github/workflows/security-scan.yml
name: 安全扫描

on:
  schedule:
    - cron: '0 2 * * *'  # 每天凌晨2点运行
  push:
    branches: [ main ]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    
    steps:
    - name: 检出代码
      uses: actions/checkout@v3
      
    - name: 运行OWASP ZAP安全扫描
      uses: zaproxy/action-full-scan@v0.7.0
      with:
        target: 'http://localhost:8080'
        rules_file_name: '.zap/rules.tsv'
        cmd_options: '-a'
        
    - name: 运行依赖漏洞扫描
      uses: snyk/actions/node@master
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      with:
        args: --severity-threshold=high
        
    - name: 运行WordPress安全扫描
      run: |
        docker run --rm 
          -v $(pwd):/app 
          wpscan/wpscan 
          --url http://localhost:8080 
          --enumerate vp,vt 
          --api-token ${{ secrets.WPSCAN_API_TOKEN }} 
          --format json 
          --output wpscan-report.json
          
    - name: 上传安全报告
      uses: actions/upload-artifact@v3
      with:
        name: security-reports
        path: |
          *.json
          *.html
          *.xml

5.2 合规性检查脚本

<?php
/**
 * 供应链系统合规性检查
 * 
 * @package SupplyChainCompliance
 */

class ComplianceChecker
{
    /**
     * 检查GDPR合规性
     */
    public function checkGDPRCompliance()
    {
        $checks = [
            'data_encryption' => $this->checkDataEncryption(),
            'data_retention' => $this->checkDataRetentionPolicy(),
            'user_consent' => $this->checkUserConsentMechanism(),
            'data_export' => $this->checkDataExportCapability(),
            'data_deletion' => $this->checkDataDeletionCapability()
        ];
        
        return [
            'compliant' => !in_array(false, $checks, true),
            'checks' => $checks,
            'timestamp' => current_time('mysql')
        ];
    }
    
    /**
     * 检查PCIDSS合规性(如果处理支付信息)
     */
    public function checkPCIDSSCompliance()
    {
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/6148.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部