有两种流行的方法可以解决这个问题。虽然您提供了许多指标(订单、评级、持续时间、收入),但让我们将示例简化为“点数”。
第一个场景是一个公式化的级别系统,您的分数概念构成一个阈值,可以即时计算。例如,>10 点始终为“银”。如果你有能力在你的系统中丢分,那么你可以在这个模型中低于银牌。
第二个是更以事件为中心的模型,其中更改阈值可以更改您的级别,但还原不会降低您的级别。这更像是您得分的“赛季最佳”得分。
我最初的想法是,你代码的复杂性来自关卡的计算,而不是存储(所以它不一定在你的模型中)。
您如何对此建模在很大程度上取决于取决于您的级别或分数的事物。一些探索性的问题是:
- 级别会影响计费等事项吗?访问服务或功能怎么样?了解这一点会影响你如何挂钩 Laravel 的授权代码(验证器、路由访问等)。
- 您的关卡公式是否适合第一种或第二种情况(人们可以退回到一个关卡)。这可以帮助您确定是要存储关卡还是始终计算它(并可能缓存它...)。
- 你的关卡系统会衰减吗?对于您的带有用户警告的示例,请让这些警告“衰减”,例如一个月,如果他们太老了,不考虑吗?这有助于您决定对评分算法的输入数据进行任何适当的缓存或过滤。
我最初的直觉是将“状态”字段映射到您的主要实体或模型。例如,您的 User 模型可能有一个 level 字段。然后,您的关卡字段中的转换可以由状态机处理(做一些进一步的谷歌搜索),该状态机会影响您的所有计算和评分算法。或者,您可以将其作为模型上的自定义访问器并动态计算它。
鉴于我最初的直觉,我只想拥有一个受保护的字段:
class User {
//...
protected $guarded = ['level'];
// ...
}
“级别”(作为 API)之间状态转换的一个很好的例子是查看 Stripe 的账单/发票工作流程。虽然它是一个非常不同的业务领域,但它是一个简单的 API,在工作流状态之间的转换中有很多复杂的。您可以将这些业务规则作为示例来了解如何构建自己的代码和数据结构。
最后,你可能想挂接到 Laravel 的事件系统以触发 'levelling' 事件,并确保这些级别之间的转换仅由一组代码处理(尽量避免在运行中计算级别一堆控制器 - 将它们整合到您的服务中)。
哦,当您考虑架构时...您是否需要存储某人的关卡历史和通过关卡“过渡”的原因?深思=D