PHP 怎么促销引擎

wen PHP项目 2

本文目录导读:

PHP 怎么促销引擎

  1. 促销引擎核心架构
  2. 促销规则引擎核心类
  3. 促销策略模式实现
  4. 条件验证器
  5. 使用示例
  6. 数据库表结构
  7. 最佳实践建议

我来为你详细讲解PHP促销引擎的设计与实现。

促销引擎核心架构

基础数据结构

<?php
// 促销规则实体
class PromotionRule {
    public int $id;
    public string $name;
    public string $type;        // discount, cash_off, buy_x_get_y, bundle
    public float $value;        // 折扣值或减免金额
    public array $conditions = []; // 适用条件
    public array $actions = [];    // 优惠动作
    public string $priority;    // 优先级别
    public string $startDate;
    public string $endDate;
    public int $usageLimit;     // 使用限制
    public int $usedCount = 0;
    public bool $isActive;
}
// 购物车上下文
class CartContext {
    public array $items = [];       // 购物车商品
    public float $subtotal = 0;     // 小计
    public float $discount = 0;     // 总折扣
    public array $appliedPromotions = []; // 已应用促销
    public Customer $customer;
    public array $metaData = [];    // 额外数据
}
// 商品条目
class CartItem {
    public int $productId;
    public int $quantity;
    public float $price;
    public array $attributes;      // 商品属性
    public array $categories;      // 商品分类
}

促销规则引擎核心类

<?php
class PromotionEngine {
    private array $rules = [];
    private array $chainStrategies = [];
    public function __construct(array $rules = []) {
        $this->rules = $rules;
        $this->initChainStrategies();
    }
    // 应用促销规则
    public function applyPromotions(CartContext $cart): CartContext {
        // 筛选可用的规则
        $applicableRules = $this->filterApplicableRules($cart);
        // 按优先级排序
        usort($applicableRules, function($a, $b) {
            return $a->priority <=> $b->priority;
        });
        // 应用促销策略
        foreach ($applicableRules as $rule) {
            if (!$this->checkRuleConditions($rule, $cart)) {
                continue;
            }
            $strategy = $this->getChainStrategy($rule->type);
            if ($strategy) {
                $strategy->execute($rule, $cart);
            }
        }
        // 更新购物车统计
        $this->updateCartTotals($cart);
        return $cart;
    }
    // 筛选可用规则
    private function filterApplicableRules(CartContext $cart): array {
        $applicable = [];
        $now = new DateTime();
        foreach ($this->rules as $rule) {
            // 检查有效性
            if (!$rule->isActive || 
                $rule->usedCount >= $rule->usageLimit) {
                continue;
            }
            // 检查时间范围
            if ($now < new DateTime($rule->startDate) || 
                $now > new DateTime($rule->endDate)) {
                continue;
            }
            $applicable[] = $rule;
        }
        return $applicable;
    }
    // 检查规则条件
    private function checkRuleConditions(PromotionRule $rule, CartContext $cart): bool {
        foreach ($rule->conditions as $condition) {
            if (!$this->evaluateCondition($condition, $cart)) {
                return false;
            }
        }
        return true;
    }
}

促销策略模式实现

<?php
// 策略接口
interface PromotionStrategy {
    public function execute(PromotionRule $rule, CartContext $cart): void;
}
// 折扣策略
class DiscountStrategy implements PromotionStrategy {
    public function execute(PromotionRule $rule, CartContext $cart): void {
        $discountAmount = $cart->subtotal * ($rule->value / 100);
        $cart->discount += $discountAmount;
        $cart->appliedPromotions[] = [
            'rule_id' => $rule->id,
            'name' => $rule->name,
            'type' => 'discount',
            'amount' => $discountAmount
        ];
    }
}
// 满减策略
class CashOffStrategy implements PromotionStrategy {
    public function execute(PromotionRule $rule, CartContext $cart): void {
        if ($cart->subtotal >= $rule->conditions['threshold']) {
            $cart->discount += $rule->value;
            $cart->appliedPromotions[] = [
                'rule_id' => $rule->id,
                'name' => $rule->name,
                'type' => 'cash_off',
                'amount' => $rule->value
            ];
        }
    }
}
// 买赠策略
class BuyXGetYStrategy implements PromotionStrategy {
    public function execute(PromotionRule $rule, CartContext $cart): void {
        $productId = $rule->conditions['product_id'];
        $buyQuantity = $rule->conditions['buy_quantity'];
        $freeQuantity = $rule->conditions['free_quantity'];
        // 找到对应商品
        foreach ($cart->items as &$item) {
            if ($item->productId === $productId) {
                $qualifiedSets = floor($item->quantity / $buyQuantity);
                if ($qualifiedSets < 1) continue;
                $freeItems = $qualifiedSets * $freeQuantity;
                // 添加赠品或折扣
                $cart->discount += $freeItems * $item->price;
                $cart->appliedPromotions[] = [
                    'rule_id' => $rule->id,
                    'name' => $rule->name,
                    'type' => 'buy_x_get_y',
                    'amount' => $freeItems * $item->price,
                    'free_items' => $freeItems
                ];
                break;
            }
        }
    }
}
// 组合捆绑策略
class BundleStrategy implements PromotionStrategy {
    public function execute(PromotionRule $rule, CartContext $cart): void {
        $bundleItems = $rule->conditions['bundle_items'];
        $bundlePrice = $rule->value;
        // 检查是否所有捆绑商品都在购物车
        $allPresent = true;
        $bundleTotal = 0;
        foreach ($bundleItems as $itemProductId) {
            $found = false;
            foreach ($cart->items as $item) {
                if ($item->productId === $itemProductId) {
                    $found = true;
                    $bundleTotal += $item->price;
                    break;
                }
            }
            if (!$found) {
                $allPresent = false;
                break;
            }
        }
        // 应用捆绑折扣
        if ($allPresent) {
            $bundleDiscount = $bundleTotal - $bundlePrice;
            $cart->discount += $bundleDiscount;
            $cart->appliedPromotions[] = [
                'rule_id' => $rule->id,
                'name' => $rule->name,
                'type' => 'bundle',
                'amount' => $bundleDiscount
            ];
        }
    }
}

条件验证器

<?php
class ConditionValidator {
    // 评估条件
    public function evaluate(array $condition, CartContext $cart): bool {
        $type = $condition['type'];
        return match($type) {
            'minimum_amount' => $this->checkMinimumAmount($condition, $cart),
            'product_quantity' => $this->checkProductQuantity($condition, $cart),
            'category' => $this->checkCategory($condition, $cart),
            'customer_group' => $this->checkCustomerGroup($condition, $cart),
            'date_range' => $this->checkDateRange($condition),
            'combinable' => $this->checkCombinable($condition, $cart),
            'location' => $this->checkLocation($condition, $cart),
            default => true
        };
    }
    // 检查最低金额
    private function checkMinimumAmount(array $condition, CartContext $cart): bool {
        $threshold = $condition['value'];
        return $cart->subtotal >= $threshold;
    }
    // 检查商品数量
    private function checkProductQuantity(array $condition, CartContext $cart): bool {
        $productId = $condition['product_id'];
        $minQuantity = $condition['quantity'] ?? 1;
        foreach ($cart->items as $item) {
            if ($item->productId === $productId && 
                $item->quantity >= $minQuantity) {
                return true;
            }
        }
        return false;
    }
    // 检查商品分类
    private function checkCategory(array $condition, CartContext $cart): bool {
        $targetCategory = $condition['category_id'];
        $minItems = $condition['min_items'] ?? 1;
        $count = 0;
        foreach ($cart->items as $item) {
            if (in_array($targetCategory, $item->categories)) {
                $count += $item->quantity;
            }
        }
        return $count >= $minItems;
    }
    // 检查客户组
    private function checkCustomerGroup(array $condition, CartContext $cart): bool {
        $groupIds = $condition['group_ids'];
        return in_array($cart->customer->groupId, $groupIds);
    }
    // 检查日期范围
    private function checkDateRange(array $condition): bool {
        $now = new DateTime();
        $start = new DateTime($condition['start']);
        $end = new DateTime($condition['end']);
        return $now >= $start && $now <= $end;
    }
    // 检查是否可叠加
    private function checkCombinable(array $condition, CartContext $cart): bool {
        $count = count($cart->appliedPromotions);
        $maxCombinable = $condition['max'] ?? 3;
        return $count < $maxCombinable;
    }
    // 检查地理位置
    private function checkLocation(array $condition, CartContext $cart): bool {
        $allowedLocations = $condition['locations'];
        return in_array($cart->metaData['location'] ?? '', $allowedLocations);
    }
}

使用示例

<?php
// 创建促销引擎实例
class PromotionService {
    private $engine;
    private $repository;
    public function __construct() {
        // 从数据库加载规则
        $rules = $this->repository->getActivePromotions();
        $this->engine = new PromotionEngine($rules);
    }
    public function applyPromotions(CartContext $cart): CartContext {
        return $this->engine->applyPromotions($cart);
    }
    public function calculateFinalPrice(CartContext $cart): float {
        $appliedCart = $this->applyPromotions($cart);
        $finalTotal = $appliedCart->subtotal - $appliedCart->discount;
        return max(0, $finalTotal);
    }
}
// 使用示例
$promotionService = new PromotionService();
// 构建购物车
$cart = new CartContext();
$cart->items = [
    (new CartItem())->withProductId(1)->withQuantity(2)->withPrice(50.00)->withCategories([1, 'electronics']),
    (new CartItem())->withProductId(2)->withQuantity(1)->withPrice(80.00)->withCategories([2, 'clothing']),
    // ... 更多商品
];
$cart->subtotal = 180.00;
$cart->customer = new Customer([
    'id' => 1,
    'groupId' => 'vip'
]);
// 应用促销
$finalPrice = $promotionService->calculateFinalPrice($cart);
echo "原价: " . $cart->subtotal . PHP_EOL;
echo "折扣: " . $cart->discount . PHP_EOL;
echo "最终价格: " . $finalPrice . PHP_EOL;
// 输出应用的所有促销
print_r($cart->appliedPromotions);

数据库表结构

-- 促销规则表
CREATE TABLE promotions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    type ENUM('discount', 'cash_off', 'buy_x_get_y', 'bundle') NOT NULL,
    value DECIMAL(10,2),
    priority INT DEFAULT 0,
    start_date DATETIME NOT NULL,
    end_date DATETIME NOT NULL,
    usage_limit INT DEFAULT NULL,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 促销条件表
CREATE TABLE promotion_conditions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    promotion_id INT NOT NULL,
    condition_type VARCHAR(50) NOT NULL,
    condition_params JSON,
    FOREIGN KEY (promotion_id) REFERENCES promotions(id)
);
-- 促销动作表
CREATE TABLE promotion_actions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    promotion_id INT NOT NULL,
    action_type VARCHAR(50) NOT NULL,
    action_params JSON,
    FOREIGN KEY (promotion_id) REFERENCES promotions(id)
);
-- 促销使用记录表
CREATE TABLE promotion_usage (
    id INT PRIMARY KEY AUTO_INCREMENT,
    promotion_id INT NOT NULL,
    order_id INT,
    user_id INT,
    discount_amount DECIMAL(10, 2),
    used_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (promotion_id) REFERENCES promotions(id)
);

最佳实践建议

1 性能优化

  • 使用缓存(Redis/Memcached)缓存规则
  • 批量加载商品和规则
  • 使用索引优化查询

2 扩展性

  • 保持策略模式以便添加新促销类型
  • 使用事件驱动架构
  • 日志记录和审计

3 测试策略

// 单元测试示例
class PromotionEngineTest extends PHPUnit\Framework\TestCase {
    public function testDiscountStrategy() {
        $rule = new PromotionRule([
            'type' => 'discount',
            'value' => 10
        ]);
        $cart = new CartContext();
        $cart->subtotal = 100;
        $strategy = new DiscountStrategy();
        $strategy->execute($rule, $cart);
        $this->assertEquals(10, $cart->discount);
    }
    // 更多测试...
}

这个促销引擎设计灵活、可扩展,适合大多数电商场景,你可以根据实际需求调整和扩展。

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