Laravel 包

Laravel 折扣:优惠券代码、使用限制和叠加使用

发布
Laravel 折扣:优惠券代码、使用限制和图片堆叠

有些 Laravel 应用在销售产品或服务时,需要的折扣不仅仅是固定的百分比。例如,电商平台可能会安排季节性促销,SaaS 产品可能会发放新品发布优惠券,而从 10% 起步的折扣可以设置上限,例如最低订单金额、每个客户的折扣次数限制以及有效期。Laravel 折扣 米尔瓦德·科斯拉维 将所有这些信息存储在 Eloquent 模型中,并通过单一外观对其进行评估。

套餐包含以下内容:

  • 两种折扣类型 : DiscountType::PercentageDiscountType::Fixed (可选) max_discount_amount 帽。
  • 优惠券代码 :折扣 code 可作为优惠券使用,而无码折扣则会自动应用。
  • 时间窗口 : starts_atexpires_at 列,与 valid() 查询范围。
  • 使用限制 : 全部的 usage_limit 按客户计费 usage_limit_per_user 执法。
  • 访客支持 :传递会话 ID 以对未经身份验证的用户强制执行每个用户的限制。
  • 堆叠规则 标记折扣 is_stackable 该软件包会计算出哪种组合能为客户节省最多费用。
  • 折扣款 : 这 HasDiscounts 该特性可为任何 Eloquent 模型附加折扣。
  • 购物车集成 :A CartDiscount 为 Laravel 购物车总金额或单个购物车商品应用代码的服务。

百分比折扣和固定折扣

折扣是 Eloquent 中的一个标准模型,因此您可以像创建其他任何记录一样创建它:

使用 Binafy\LaravelDiscount\Enums\DiscountType ;
使用 Binafy\LaravelDiscount\Models\Discount ;
$折扣 = 折扣 :: 询问 () -> 创造 ([
'姓名' => “夏季促销” ,
'类型' => 折扣类型 :: 百分比 ,
'价值' => 20 ,
]);

应用它需要经过…… LaravelDiscount 门面会在计算任何内容之前验证折扣,然后返回一个 DiscountResult :

使用 Binafy\LaravelDiscount\Facades\LaravelDiscount ;
$结果 = Laravel折扣 :: 申请 (折扣) 200 (英文):
$结果 -> 原金额; // 200.0
$结果 -> 折扣金额; // 40.0
$结果 -> 应付金额 (); // 160.0

DiscountResult 该对象包含已应用的折扣、原始总额和计算出的折扣值。 payableAmount() 从原始总额中减去折扣,并将结果限制在最小值为零,以确保固定折扣永远不会产生负总额。

任何类型的折扣都可能存在上限。 max_discount_amount 这就涵盖了“最高优惠 100 美元,享受 20% 折扣”的情况,否则这种情况最终会被硬编码到控制器中:

$折扣 = 折扣 :: 询问 () -> 创造 ([
'代码' => “节省20元” ,
'类型' => 折扣类型 :: 百分比 ,
'价值' => 20 ,
'max_discount_amount' => 100 ,
]);
Laravel折扣 :: 申请 (折扣) 300 -> 折扣金额; // 60.0
Laravel折扣 :: 申请 (折扣) 1000 -> 折扣金额; // 100.0

折扣码、有效期和使用限制

设置 code 专栏将折扣转换为促销优惠券。 applyCode() 验证代码并抛出异常 DiscountNotFoundException 如果没有匹配项:

$结果 = Laravel折扣 :: applyCode 'WELCOME10' , 200 ,$user);

对于每个客户都需要自己代码的营销活动,该软件包会使用以下方式构建代码: random_int() 并省略了模棱两可的角色,例如 0 / O1 / I 这样就不会有人误读打印卡片上的代码了:

Laravel折扣 :: 生成代码 (); // "8FJ2K9QW"
Laravel折扣 :: 生成代码 100 , “VIP” (英文): // 包含 100 个唯一代码的集合

长度、字母、前缀和分隔符都属于以下范畴: codes 键入 config/laravel-discount.php

限时优惠使用 starts_atexpires_at 在窗口弹出之前申请 DiscountNotStartedException ,在抛出后应用 DiscountExpiredException 并开火 DiscountExpired 事件。查询当前正在直播的内容是一个范围:

折扣 :: 询问 () -> 有效的 () -> 得到 ();

usage_limit 限制总兑换额,以及 usage_limit_per_user 对每位客户设定上限,但这些上限并非仅在申请时就确定。您致电 redeem() 当订单最终确定时:

Laravel折扣 :: 赎回 (折扣,用户,结果) -> 折扣金额);

该操作在事务中运行并递增。 used_count 受限于 where 子句决定数据库是否执行增量更新。如果更新零行,则已达到限制,这会表现为: DiscountUsageLimitReachedException 两个顾客同时声称自己是第一百名顾客,不可能同时获得该名额。

访客通过会话 ID 而非用户模型获得相同的待遇,该 ID 会在跟踪过程中进行记录。 session_iddiscount_usages 与可空对象一起 user_id :

$结果 = Laravel折扣 :: applyCode 'GUEST10' 总计 会话 ID : 会议 () -> 获取 ID ());
Laravel折扣 :: 赎回 (折扣) 数量 :$result -> 折扣金额 会话 ID : 会议 () -> 获取 ID ());

条件折扣和可叠加折扣

A min_order_value 专栏设置了消费门槛,达到一定金额后即可享受折扣,并会抛出一些问题。 MinimumOrderValueException 当总数不足时。还有一种情况是…… conditions 用于存储自定义条件数据的 JSON 列,您可以将软件包本身未原生支持的所有内容都放在这里。如果您希望条件以可组合的 PHP 对象形式表示,则需要使用 JSON 列。 Discountify套餐 采取这种方法。

折扣也可以适用于特定型号。添加 HasDiscounts 性状,并由此获得由以下因素支持的多态关系: discountables 桌子:

使用 Binafy\LaravelDiscount\Traits\HasDiscounts ;
班级 产品 延伸 模型
{
使用 有折扣 ;
}
$产品 -> 折扣 () -> (折扣)
$产品 -> 有效折扣 ();
$产品 -> 有折扣 'TECH10' (英文):
$结果 = $产品 -> 应用折扣 (产品) -> 价格);

最后一个呼叫通过 applyMany() 这是堆叠解析器。它会丢弃任何未通过验证的折扣,将剩余的折扣拆分为可堆叠折扣和不可堆叠折扣,将可堆叠折扣相加(上限为订单总额),找到最佳的不可堆叠折扣,并返回节省金额更多的一方:

$结果 = Laravel折扣 :: 应用多个 ([$tenPercent, $tenFixed, $bigSolo], 100 (英文):
$结果 -> 折扣; // 实际应用的那些
$结果 -> 折扣金额; // 获胜总额

discounts 收集结果至关重要。在做出堆叠决策后,您通常需要向客户展示哪些代码最终入选,而收集结果就是答案。

Laravel 购物车集成

安装 binafy/laravel-cart 购物车包来自同一作者,我们 之前已介绍过 ,和一个 CartDiscount 该服务支持购物车级别和商品级别折扣:

使用 Binafy\LaravelDiscount\Integrations\LaravelCart\CartDiscount ;
购物车折扣 = 应用程序 购物车折扣 ::班级 (英文):
$结果 = 购物车折扣 -> 添加到购物车 (购物车, 'SUMMER-8FJ2K9QW' (英文):
$结果 = 购物车折扣 -> 应用于项目 ($购物车商品,$折扣);
$结果 = 购物车折扣 -> 应用商品折扣 (购物车)

applyToCart() 检查购物车总额是否与预期相符 min_order_value 并根据每个用户的限制,从购物车中提取用户,这样你自己就不会超过这两个限制。 applyToItem() 单行价格乘以数量计算。 applyItemDiscounts() 它遍历购物车,并应用每个物品底层模型所附加的任何内容。 HasDiscounts 也就是说,你可以在不改变购物车总额的情况下,对整个购物篮中的商品进行产品级销售。

验证、异常和事件

结账表单需要先拒绝无效代码,然后才能进行其他操作,并且该软件包包含一个 ValidDiscountCode 这条规则就是如此。它的错误消息会明确指出实际原因,而不是泛泛地报错:

使用 Binafy\LaravelDiscount\Rules\ValidDiscountCode ;
民众 功能 规则 () : 大批
{
返回 [
'代码' => [ '必需的' , 新的 有效折扣码
订单金额 : $this -> 购物车总计 (),
用户 : $this -> 用户 (),
)],
];
}

这是一个标准规则对象,因此它与其他表单请求元素的组合方式与任何其他规则对象相同。 自定义验证规则 做。

除了验证之外,每个失败案例都有其自身的异常扩展。 DiscountException : DiscountNotFoundException , DiscountNotActiveException , DiscountNotStartedException , DiscountExpiredException , DiscountUsageLimitReachedException , 和 MinimumOrderValueException 每一项都暴露了折扣失败的真相。 getDiscount() 这样,你就可以针对需要特殊处理的情况进行单独消息传递,而让基类处理其余部分:

尝试 {
$结果 = Laravel折扣 :: applyCode ($代码,$总计,$用户);
} 抓住 折扣过期异常 $e) {
返回 后退 () -> 带有错误 “代码 { $e -> 获取折扣 () -> 代码 已过期。 (英文):
} 抓住 折扣例外 $e) {
返回 后退 () -> 带有错误 ($e -> 获取消息 ());
}

生命周期包含三个事件: DiscountApplied 当折扣应用于某个金额时, DiscountRedeemed 赎回交易提交后,并且 DiscountExpired 当验证过程中发现折扣已过期时,兑换事件会同时包含折扣信息和使用记录,这足以驱动分析或发送通知,无需再次查询。

安装

Laravel Discount 需要 PHP 8.1+ 和 Laravel 9-13。通过 Composer 安装该软件包并运行迁移:

作曲家 要求 binafy/laravel-discount
php 工匠 迁移

服务提供商注册自身,迁移过程创建 discounts , discount_usages , 和 discountables 发布配置是可选的,只有当您需要更改表名、指向不同的用户模型或调整代码生成默认值时才值得这样做:

php 工匠 供应商:发布 --标签= "laravel-discount-config"

它还附带两条工匠指令。 discount:generate 从终端生成代码,并且 discount:prune 删除过期折扣及其使用记录,这是计划任务中应该包含的一项合理内容:

日程 :: 命令 'discount:prune --days=30' -> 日常的 ();

完整的文档,包括配置参考,位于…… Laravel 折扣 GitHub 仓库

Yannick Lyn Fatt 的照片

Laravel News 的特约撰稿人和全栈 Web 开发人员。

归档于

赞助

掌握 Laravel 标志
Laravel 代码审查

几天内即可获得 Laravel 代码审查方面的专家指导

访问 Laravel 代码审查
组合:多列上的精妙关系图

组合:多列上的精妙关系

阅读文章
MKSine:一款基于 Filament 的 CMS,支持插件、主题和模块(图片)

MKSine:一款基于 Filament 的内容管理系统,支持插件、主题和模块

阅读文章
在 Inertia.js v3.7 图片中取消飞行中表单提交

在 Inertia.js v3.7 中取消飞行中表单提交

阅读文章
Laravel Starter Kits 现在附带 Vite+ 图片

Laravel Starter Kits 现在随附 Vite+

阅读文章
Laravel Eloquent 中使用 refreshForUpdate() 实现悲观锁定 图片

Laravel Eloquent 中使用 refreshForUpdate() 实现悲观锁定

阅读文章
Laravel 异常消息中的掩码查询绑定图片

Laravel 异常消息中的查询绑定掩码

阅读文章