返佣系统需用path字段(如"0-100-205-318")存储分销关系并配置化佣金比例,佣金逻辑须抽离为独立服务类,通过事件驱动解耦,且发放操作需幂等性保障。

返佣系统不是加个“分钱逻辑”就能跑通的,核心矛盾在数据结构选型和事件驱动设计——选错 path 字段或把佣金写进控制器,上线后查账、补单、调级全得重写。
path 字段怎么存分销关系才不翻车
用 parent_id 递归查三级下线?订单结算时查一次要 3 次 JOIN,1000 笔订单就拖垮数据库。必须用 path 字段(如 "0-100-205-318")。
-
path开头固定为"0",避免空字符串导致LIKE查询失效 - 注册时必须同步更新:
$user->path = $parent ? $parent->path . '-' . $parent->id : '0',别依赖模型事件——事务里可能漏掉 - 层级超 5 级,
path字段类型至少设为VARCHAR(255),否则截断后查不到下级 - 查某用户所有下级:用
WHERE path LIKE '0-100-%',再用LENGTH(path) - LENGTH(REPLACE(path, '-', '')) - 1算出相对级差
佣金计算逻辑必须抽成独立服务类
写在订单控制器里?退款、冻结上级、调整比例时就得改三处代码,发错钱没人兜底。
- 新建
CommissionService类,所有佣金动作(发放、回退、重算)只走这一个入口 - 通过 ThinkPHP 事件驱动:
event('OrderPaid', $order)、event('RefundSucceed', $refund),解耦业务与结算 - 佣金比例必须配置化,存在数据库表或
config/commission.php中:'levels' => [1 => 10, 2 => 5, 3 => 2],禁止硬编码 - 涉及金额操作必须用事务包裹,且
commission_record表要记录每笔明细,字段含order_id、user_id、amount、type(in/out)、source_path
查下级并按级分组的实际写法
想直接 SQL 分出“一级下线”“二级下线”?MySQL 原生不支持层级偏移,得靠字符串处理或 PHP 侧拆解。
- SQL 查全量下级:
User::where('path', 'like', $user->path . '-%')->select() - 要分组,推荐 PHP 侧处理:
$ids = explode('-', $path); $level1 = $ids[1] ?? null; $level2 = $ids[2] ?? null; - 千万别用
with(['parent'])做 N+1 查询——1000 个下线 = 1000 次 SQL,DB 直接卡死 - 高并发结算场景建议预生成闭包表(
user_ancestor),但中小项目用path+ 缓存更省事
最易被忽略的是佣金发放的幂等性:同一笔订单触发两次 OrderPaid 事件,不能发两笔钱。必须在 commission_record 表加唯一索引(order_id + user_id + level),而不是靠代码判断“是否已发”。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











