本文目录导读:

我来为你详细讲解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);
}
// 更多测试...
}
这个促销引擎设计灵活、可扩展,适合大多数电商场景,你可以根据实际需求调整和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播