【问题标题】:How to handle complex user status?如何处理复杂的用户状态?
【发布时间】:2015-12-31 02:16:00
【问题描述】:

我的应用程序处理用户付款。在公司,该用户的状态如下:

  • 合规(用户已偿还所有债务)
  • 逾期/违约(用户至少注册 3 个月且未偿还至少 1 笔债务)
  • 不活跃(用户注册不足 3 个月且未偿还任何债务)

在应用程序内的多个地方(和规则)处理这些规则的最佳方式是什么?

我需要像 status_id 这样的字段和一个 cron 来每小时更新一次吗?

没有status_id字段并在每个需要显示状态的查询中编写SQL规则?

加载User 模型并调用具有规则的->status() 方法?在这种情况下,如何显示“总数”,例如:我们有 3000 个过期用户、15000 个非活动用户等...

这让我头痛了好几个月,我真的需要帮助哈哈。我们目前有一个解决方案,但处理起来太复杂了。由于它似乎在处理支付的应用程序中很常见,因此必须有一种更简单的方法来做到这一点:P

谢谢!

备注

  • 应用目前有 90.000 个用户
  • 我们需要这些实时信息。
  • 此信息在报告中用于生成字符。
  • 此信息显示在用户个人资料中。
  • 此信息显示在列表中。
  • 当用户在这些状态之间发生变化时会通知用户(例如,当用户输入“逾期”时,“您有债务”)。
  • 此信息由应用程序用户管理。
  • 需要跟踪状态。

【问题讨论】:

    标签: php mysql database oop conceptual


    【解决方案1】:

    如果您在多个地方使用此字段,那么您应该将状态存储在一个地方并根据需要进行更新(我也会保留状态的历史记录,但这是另一回事)。

    如果状态因某些用户操作(例如正在处理的付款)而发生变化,那么您可以在操作上使用触发器。但是,您的状态更改似乎是基于事件发生后的时间。在这种情况下,您应该运行定期安排的作业(作为 cron 作业或数据库事件)。

    我有点困惑为什么你会每小时都这样做。似乎每天一次是最合适的。如果“债务”是在任意时间支付的,那么支付过程应该更新状态。对于状态的降级,一个作业每天一次就足够了。

    【讨论】:

    • “每小时”只是更新过程运行频率的一个示例。是的,状态是根据用户操作更新的,不一定是在事件发生后的某个时间,因此,更新将是即时的。您的解决方案很棒,我正在将其与 @Chris' 结合使用,感谢您的帮助!
    【解决方案2】:

    有趣的问题,但也没有一个答案。

    我认为这里的复杂性可能来自周围的代码,而不是核心业务逻辑和需求。我这样说是因为三种状态类型,它们都源自您的内部应用程序,并没有 糟糕。

    一种可能的解决方案,我假设某种级别的 MVC 或类似的。

    给定您的模型user,并扩展像 Eloquent 这样的 ORM(我将从 Laravel 中选择 Eloquent,因为我最熟悉它,但任何 ORM 都可以使用):

    use Illuminate\Database\Eloquent\Model;
    use App\DebtCollector;
    
    public class User extends Model
    {
        // Assuming model has the following fields
        // id, status, registration_date, and a one to many
        // relationship with debts 
    
        protected $fillable = [
            'raw_status',
            'registration_date',
        ];
    
        public function debts()
        {
            return $this->hasMany(Debt::class);
        }
    
        public function refreshStatus()
        {
            $dc = new DebtCollector();
    
            // Business logic inside the "DebtCollector" class
            $this->raw_status = $dc->resolveStatus($this->debts, $this->registration_date);
    
            // Save value to the underlying datebase
            $this->save();            
        }
    
        // If you fetch a status directly, it will refresh first, 
        // then return the value
        // 
        public function getStatusAttribute()
        {
            $this->refreshStatus();
            return $this->raw_status;
        }
    }
    
    
    // Schedule task somewhere - ran nightly, or whenever
    // 
    // This way you can refresh the status only on certain groups
    // of data - for example, if the business flow means that once
    // they become compliant, they can't go back, there is no need
    // to refresh their status anymore 
    //
    User::where('raw_status', '<>', 'compliant')->refreshStatus();
    
    // Alternatively, the schedule could chunk results and do an update
    // only to those not updated in the last 24 hours
    //
    $date = new DateTime;
    $date->modify('-24 hours');
    $formatted_date = $date->format('Y-m-d H:i:s');
    User::where('last_updated', '>', $formatted_data)->refreshStatus();
    

    【讨论】:

    • “还不错”,很高兴听到这个消息哈哈哈:P。就是这样!调用refreshStatus 并构建StatusResolver 类/方法是可行的方法。非常感谢!我会将您的答案与@Gordon 答案的历史数据结合起来,希望我们不再需要重构它。
    【解决方案3】:

    我想说这个问题有多种解决方案。

    我建议不要有任何定义的状态。据我所知,您始终可以根据其他一些数据“弄清楚”当前状态。 例如“用户到目前为止还清了所有债务”。只需分析给定时期的所有变化,您就可以轻松了解这一点。您可以汇总数据以找出您需要知道的所有信息。因此,您根本不需要保存状态。它只是从特定时期内客户帐户发生的所有更改中得出的。

    总数也是如此。您可以在数据库级别轻松完成此操作,甚至可以使用一些基于文档的 DB 或 ElasticSearch。

    当然,这假设您跟踪更改的历史。如果你这样做 - 问题解决了。如果您不这样做 - 您必须将状态保存到数据库中,并且无法获取历史数据。

    【讨论】:

    • 今天应用程序的工作方式与您描述的一样。每次我们需要它时,它都会“计算出”状态。问题是:“计算”过程涉及大约 4~5 个连接,因为我还需要知道诸如“未支付的债务来自一个有效的订单?另外,某些用户类型可能会收到不同的状态不一定与债务本身有关。今天,我们有一个“解决”状态的 sql 块,但是在我们的查询中维护和插入它是很烦人的。你会建议(技术上)在不保存的情况下处理这个问题状态?我对此很感兴趣。
    • @FelipeFrancisco 在您已经拥有用户列表后,您可以通过发出第二个查询轻松地做到这一点。并在返回之前合并数据。这样你就有了一个单一的事实。您仍然需要记住添加状态详细信息,但这可以在对象级别和测试中轻松处理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-30
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-08
    相关资源
    最近更新 更多