位置: 文档库 > PHP > PHP商城开发教程:如何添加优惠券功能和管理页面

PHP商城开发教程:如何添加优惠券功能和管理页面

海盐日历2178 上传于 2022-06-22 03:20

《PHP商城开发教程:如何添加优惠券功能和管理页面》

在电商系统中,优惠券功能是提升用户转化率和复购率的核心模块之一。本文将通过完整的PHP实现流程,详细讲解如何为商城系统添加优惠券功能,包括数据库设计、核心逻辑实现、前端交互及管理后台开发。通过分步骤的代码示例和系统架构分析,帮助开发者快速掌握从零构建优惠券系统的关键技术点。

一、数据库设计

优惠券系统需要设计三张核心表:优惠券模板表、用户优惠券表和订单关联表。

1.1 优惠券模板表(coupon_templates)

CREATE TABLE `coupon_templates` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL COMMENT '优惠券名称',
  `type` tinyint(1) NOT NULL COMMENT '1-满减券 2-折扣券 3-无门槛券',
  `discount_amount` decimal(10,2) DEFAULT NULL COMMENT '满减金额/折扣金额',
  `min_order_amount` decimal(10,2) DEFAULT NULL COMMENT '最低消费金额',
  `discount_rate` decimal(5,2) DEFAULT NULL COMMENT '折扣率(百分比)',
  `total_count` int(11) NOT NULL COMMENT '总发放数量',
  `remaining_count` int(11) NOT NULL COMMENT '剩余数量',
  `start_time` datetime NOT NULL COMMENT '生效开始时间',
  `end_time` datetime NOT NULL COMMENT '生效结束时间',
  `status` tinyint(1) DEFAULT '1' COMMENT '1-启用 0-禁用',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='优惠券模板表';

1.2 用户优惠券表(user_coupons)

CREATE TABLE `user_coupons` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT '用户ID',
  `template_id` int(11) NOT NULL COMMENT '模板ID',
  `code` varchar(20) NOT NULL COMMENT '优惠券码',
  `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0-未使用 1-已使用 2-已过期',
  `get_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '领取时间',
  `use_time` datetime DEFAULT NULL COMMENT '使用时间',
  `order_id` int(11) DEFAULT NULL COMMENT '关联订单ID',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_code` (`code`),
  KEY `idx_user` (`user_id`),
  KEY `idx_template` (`template_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户优惠券表';

1.3 订单优惠券关联表(order_coupons)

CREATE TABLE `order_coupons` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL COMMENT '订单ID',
  `coupon_id` int(11) NOT NULL COMMENT '用户优惠券ID',
  `deduct_amount` decimal(10,2) NOT NULL COMMENT '抵扣金额',
  PRIMARY KEY (`id`),
  KEY `idx_order` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单优惠券关联表';

二、核心功能实现

2.1 优惠券发放逻辑

发放逻辑包含两种方式:系统自动发放和用户手动领取。以下为手动领取的核心代码:

class CouponService {
    public function receiveCoupon($userId, $templateId) {
        $template = $this->getTemplateById($templateId);
        if (!$template || $template['remaining_count'] hasUserReceived($userId, $templateId)) {
            throw new Exception('您已领取过该优惠券');
        }
        
        // 生成唯一优惠券码
        $code = $this->generateCouponCode();
        
        // 插入用户优惠券记录
        $data = [
            'user_id' => $userId,
            'template_id' => $templateId,
            'code' => $code,
            'status' => 0
        ];
        
        $couponId = Db::name('user_coupons')->insertGetId($data);
        
        // 更新模板剩余数量
        Db::name('coupon_templates')
            ->where('id', $templateId)
            ->dec('remaining_count')
            ->update();
            
        return $couponId;
    }
    
    private function generateCouponCode() {
        return 'CPN' . strtoupper(uniqid());
    }
}

2.2 优惠券使用验证

在订单结算时需要验证优惠券的有效性,核心验证逻辑如下:

class OrderService {
    public function applyCoupon($userId, $orderAmount, $couponCode) {
        $coupon = Db::name('user_coupons')
            ->alias('uc')
            ->join('coupon_templates ct', 'uc.template_id = ct.id')
            ->where('uc.code', $couponCode)
            ->where('uc.user_id', $userId)
            ->where('uc.status', 0)
            ->where('ct.start_time where('ct.end_time >=', now())
            ->find();
            
        if (!$coupon) {
            throw new Exception('无效的优惠券');
        }
        
        // 验证最低消费
        if ($coupon['min_order_amount'] > $orderAmount) {
            throw new Exception('订单金额不满足使用条件');
        }
        
        // 计算抵扣金额
        $deductAmount = 0;
        switch ($coupon['type']) {
            case 1: // 满减券
                $deductAmount = $coupon['discount_amount'];
                break;
            case 2: // 折扣券
                $deductAmount = $orderAmount * ($coupon['discount_rate'] / 10);
                break;
            case 3: // 无门槛券
                $deductAmount = $coupon['discount_amount'];
                break;
        }
        
        // 更新优惠券状态
        Db::name('user_coupons')
            ->where('id', $coupon['id'])
            ->update([
                'status' => 1,
                'use_time' => now()
            ]);
            
        return [
            'coupon_id' => $coupon['id'],
            'deduct_amount' => $deductAmount
        ];
    }
}

三、管理后台开发

3.1 优惠券列表页面

使用ThinkPHP框架实现分页查询:

// Controller层
public function index() {
    $params = input('get.');
    $where = [];
    
    if (!empty($params['name'])) {
        $where['name'] = ['like', '%' . $params['name'] . '%'];
    }
    
    if (isset($params['status'])) {
        $where['status'] = $params['status'];
    }
    
    $list = Db::name('coupon_templates')
        ->where($where)
        ->order('create_time desc')
        ->paginate(10);
        
    $this->assign('list', $list);
    $this->assign('params', $params);
    return $this->fetch();
}

对应的View层(HTML+Bootstrap):


        {volist name="list" id="vo"}
        
        {/volist}
    
ID 优惠券名称 类型 面额/折扣 使用条件 有效期 状态 操作
{$vo.id} {$vo.name} {switch name="vo.type"} {case value="1"}满减券{/case} {case value="2"}折扣券{/case} {case value="3"}无门槛券{/case} {/switch} {if condition="$vo.type eq 1 || $vo.type eq 3"} ¥{$vo.discount_amount} {else /} {$vo.discount_rate}% {/if} {if condition="$vo.min_order_amount gt 0"}满{$vo.min_order_amount}元可用{/if} {$vo.start_time|date='Y-m-d'} 至 {$vo.end_time|date='Y-m-d'} {eq name="vo.status" value="1"}启用 {else /}禁用{/eq} 编辑

3.2 添加/编辑优惠券

表单处理逻辑:

public function save() {
    $data = input('post.');
    
    // 数据验证
    $validate = new \app\common\validate\CouponValidate();
    if (!$validate->check($data)) {
        $this->error($validate->getError());
    }
    
    // 处理折扣率(百分比转换)
    if ($data['type'] == 2) {
        $data['discount_rate'] = $data['discount_rate'] * 10;
    }
    
    if (empty($data['id'])) {
        // 新增
        $result = Db::name('coupon_templates')->insert($data);
    } else {
        // 编辑
        $result = Db::name('coupon_templates')
            ->where('id', $data['id'])
            ->update($data);
    }
    
    if ($result) {
        $this->success('操作成功');
    } else {
        $this->error('操作失败');
    }
}

四、前端交互优化

4.1 优惠券选择弹窗

使用jQuery实现优惠券选择功能:

function showCouponList(userId) {
    $.ajax({
        url: '/coupon/userList',
        type: 'GET',
        data: {userId: userId},
        success: function(res) {
            let html = '';
            res.data.forEach(item => {
                html += `
                

${item.name}

${getCouponDesc(item)}

有效期至:${item.end_time}

`; }); $('#couponModal .modal-body').html(html); $('#couponModal').modal('show'); } }); } function getCouponDesc(coupon) { switch(coupon.type) { case 1: return `满${coupon.min_order_amount}元减${coupon.discount_amount}元`; case 2: return `${coupon.discount_rate/10}折优惠`; case 3: return `无门槛立减${coupon.discount_amount}元`; } }

五、安全与性能优化

5.1 并发控制

在发放优惠券时使用数据库事务和乐观锁防止超发:

public function safeReceive($userId, $templateId) {
    Db::startTrans();
    try {
        $template = Db::name('coupon_templates')
            ->where('id', $templateId)
            ->where('remaining_count', '>', 0)
            ->lock(true) // 行锁
            ->find();
            
        if (!$template) {
            throw new Exception('优惠券已领完');
        }
        
        // 生成优惠券码并插入记录
        $couponId = $this->insertUserCoupon($userId, $templateId);
        
        // 更新剩余数量(使用version乐观锁)
        $affected = Db::name('coupon_templates')
            ->where('id', $templateId)
            ->where('remaining_count', '>', 0)
            ->dec('remaining_count')
            ->update();
            
        if ($affected === 0) {
            throw new Exception('并发领取失败,请重试');
        }
        
        Db::commit();
        return $couponId;
    } catch (Exception $e) {
        Db::rollback();
        throw $e;
    }
}

5.2 缓存策略

使用Redis缓存热门优惠券信息:

public function getHotCoupons() {
    $cacheKey = 'hot_coupons';
    $coupons = cache($cacheKey);
    
    if (!$coupons) {
        $coupons = Db::name('coupon_templates')
            ->where('status', 1)
            ->where('end_time', '>', now())
            ->order('total_count desc')
            ->limit(10)
            ->select();
            
        cache($cacheKey, $coupons, 3600); // 1小时缓存
    }
    
    return $coupons;
}

六、完整系统架构

优惠券系统建议采用分层架构:

  • 表现层:HTML/CSS/JS前端页面
  • 控制层:PHP控制器处理请求
  • 服务层:CouponService处理核心逻辑
  • 数据层:Model与数据库交互
  • 缓存层:Redis加速数据访问

关键词:PHP商城开发、优惠券功能、数据库设计、ThinkPHP框架、并发控制缓存策略管理后台开发电商系统架构

简介:本文详细讲解了PHP商城系统中优惠券功能的完整实现方案,包含数据库设计、核心业务逻辑、管理后台开发、前端交互及安全优化等内容。通过分步骤的代码示例和系统架构分析,帮助开发者快速掌握优惠券系统的开发要点,适用于电商平台的促销功能实现。

PHP相关