《PHP商城开发教程:手把手教你实现优惠券功能》
在电商系统中,优惠券功能是提升用户转化率和复购率的核心模块之一。本文将通过完整的PHP实现流程,从数据库设计到前端交互,逐步讲解如何为商城系统开发一个可复用的优惠券功能。内容涵盖优惠券类型定义、发放逻辑、使用规则校验以及与订单系统的集成。
一、功能需求分析
优惠券系统需支持以下核心功能:
二、数据库设计
设计三张核心数据表:
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 '最低消费金额',
`valid_days` int(11) DEFAULT NULL COMMENT '有效期(天)',
`start_time` datetime DEFAULT NULL COMMENT '生效时间',
`end_time` datetime DEFAULT NULL COMMENT '失效时间',
`goods_category_ids` varchar(255) DEFAULT NULL COMMENT '适用商品分类ID',
`total_count` int(11) NOT NULL COMMENT '发放总量',
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
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(32) NOT NULL COMMENT '优惠券码',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态:0未使用 1已使用 2已过期',
`order_id` int(11) DEFAULT NULL COMMENT '关联订单ID',
`obtained_at` datetime NOT NULL COMMENT '获取时间',
`expired_at` datetime NOT NULL COMMENT '过期时间',
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 优惠券使用记录表(coupon_logs)
CREATE TABLE `coupon_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`coupon_id` int(11) NOT NULL,
`order_id` int(11) NOT NULL,
`used_amount` decimal(10,2) NOT NULL COMMENT '抵扣金额',
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
三、核心功能实现
1. 优惠券发放服务
创建CouponService类处理发放逻辑:
class CouponService {
public function issueCoupon($userId, $templateId) {
$template = $this->getTemplateById($templateId);
if (!$template || $template['remaining_count'] generateCouponCode();
// 计算过期时间
$expiredAt = $template['valid_days'] > 0
? date('Y-m-d H:i:s', strtotime("+{$template['valid_days']} days"))
: $template['end_time'];
// 插入用户优惠券记录
$userCoupon = [
'user_id' => $userId,
'template_id' => $templateId,
'code' => $code,
'status' => 0,
'obtained_at' => date('Y-m-d H:i:s'),
'expired_at' => $expiredAt
];
$couponId = Db::name('user_coupons')->insertGetId($userCoupon);
// 更新模板剩余数量
Db::name('coupon_templates')
->where('id', $templateId)
->dec('remaining_count')
->update();
return $couponId;
}
private function generateCouponCode() {
return strtoupper(substr(md5(uniqid()), 0, 8));
}
}
2. 优惠券使用校验
在订单确认页面需要验证优惠券有效性:
class CouponValidator {
public function validate($couponCode, $userId, $orderAmount) {
$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('uc.expired_at >', date('Y-m-d H:i:s'))
->find();
if (!$coupon) {
throw new Exception('优惠券无效或已过期');
}
// 检查最低消费
if ($coupon['min_order_amount'] > 0 &&
$orderAmount
3. 订单系统集成
在创建订单时应用优惠券:
class OrderService {
public function createOrder($userId, $goodsList, $couponCode = null) {
// 计算商品总价
$orderAmount = $this->calculateGoodsTotal($goodsList);
// 验证优惠券
$coupon = null;
$discountAmount = 0;
if ($couponCode) {
try {
$couponValidator = new CouponValidator();
$coupon = $couponValidator->validate($couponCode, $userId, $orderAmount);
$discountAmount = $couponValidator->calculateDiscount($coupon, $orderAmount);
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
// 最终支付金额
$payAmount = $orderAmount - $discountAmount;
// 创建订单记录...
$orderId = $this->insertOrderRecord(/* 参数 */);
// 如果使用了优惠券,更新状态并记录
if ($coupon) {
Db::name('user_coupons')
->where('id', $coupon['id'])
->update([
'status' => 1,
'order_id' => $orderId,
'used_at' => date('Y-m-d H:i:s')
]);
Db::name('coupon_logs')->insert([
'user_id' => $userId,
'coupon_id' => $coupon['id'],
'order_id' => $orderId,
'used_amount' => $discountAmount,
'created_at' => date('Y-m-d H:i:s')
]);
}
return $orderId;
}
四、前端交互实现
1. 优惠券列表展示
// AJAX获取用户优惠券
public function getUserCoupons() {
$userId = session('user_id');
$coupons = Db::name('user_coupons')
->alias('uc')
->field('uc.*, ct.name, ct.type, ct.discount_amount, ct.min_order_amount')
->join('coupon_templates ct', 'uc.template_id = ct.id')
->where('uc.user_id', $userId)
->where('uc.status', 0)
->where('uc.expired_at >', date('Y-m-d H:i:s'))
->select();
return json(['coupons' => $coupons]);
}
2. 优惠券选择组件
五、高级功能扩展
1. 优惠券堆叠使用
修改验证逻辑支持多张优惠券叠加:
public function validateMultipleCoupons($couponCodes, $userId, $orderAmount) {
$coupons = [];
$totalDiscount = 0;
foreach ($couponCodes as $code) {
try {
$validator = new CouponValidator();
$coupon = $validator->validate($code, $userId, $orderAmount - $totalDiscount);
$discount = $validator->calculateDiscount($coupon, $orderAmount - $totalDiscount);
$coupons[] = $coupon;
$totalDiscount += $discount;
// 防止超额抵扣
if ($totalDiscount >= $orderAmount) break;
} catch (Exception $e) {
// 收集错误信息
}
}
return [
'valid_coupons' => $coupons,
'total_discount' => $totalDiscount,
'errors' => /* 错误信息 */
];
}
2. 定时任务处理过期优惠券
创建Cron任务每天执行:
// artisan命令方式
public function handle() {
$expiredCoupons = Db::name('user_coupons')
->where('expired_at', 'where('status', 0)
->select();
foreach ($expiredCoupons as $coupon) {
Db::name('user_coupons')
->where('id', $coupon['id'])
->update(['status' => 2]);
}
$this->info('处理完成,共过期' . count($expiredCoupons) . '张优惠券');
}
六、安全与性能优化
1. 防刷机制
// 限制单个用户领取次数
public function checkUserLimit($userId, $templateId) {
$count = Db::name('user_coupons')
->where('user_id', $userId)
->where('template_id', $templateId)
->where('status', '', 2)
->count();
$template = Db::name('coupon_templates')->find($templateId);
if ($count >= $template['user_limit']) {
throw new Exception('已达到领取上限');
}
}
2. 数据库索引优化
ALTER TABLE `user_coupons` ADD INDEX `idx_user_status` (`user_id`, `status`);
ALTER TABLE `coupon_templates` ADD INDEX `idx_type_status` (`type`, `status`);
七、测试用例设计
必须覆盖的测试场景:
正常领取和使用流程
过期优惠券自动标记
最低消费不足时的拦截
商品类别限制验证
并发领取时的库存控制
关键词:PHP商城开发、优惠券系统、数据库设计、满减券、折扣券、无门槛券、优惠券校验、订单集成、定时任务、安全优化
简介:本文详细讲解了PHP商城系统中优惠券功能的完整实现方案,包含数据库设计、核心服务类开发、前后端交互、高级功能扩展及安全优化等内容,适合中高级PHP开发者学习电商系统核心模块开发。