首页 > 解决方案 > 在 Laravel 观察者中使用自定义 for 循环

问题描述

我想在发生更新事件时开始倒计时,并根据 laravel 5.8 API 应用程序中的某些条件更新其他字段。

基本上,这些是我想要完成的步骤

  1. 当订单表orderStatus字段更新为 时processing,开始倒计时 12 分钟。

  2. 在倒计时期间,如果订单表paymentStatus字段更新自pending,则停止倒计时并更新orderStatuscompleted

  3. 在倒计时结束时,如果订单paymentStatus仍处于待处理状态,请更新orderStatuscompletedpaymentStatusaborted

为了实现这一点,我制作了一个 OrderObserver 来监听更新事件并尝试了这段代码

public function updated(Order $order)
{
    if ($order->paymentStatus == 'paid') {

        $order->update(['orderStatus' => 'completed']);
    }

    if ($order->paymentStatus == 'processing') {

        // start a timeout function
        for ($orderedAt = $order->created_at; $orderedAt <= $orderedAt->addMinutes(12); $orderedAt->addSecond()) {
            if ($order->paymentStatus !== 'pending') {
                $order->update(['orderStatus' => 'completed']);
                break;
            }

            if ($orderedAt == $orderedAt->addMinutes(12)) {
                $order->update(['orderStatus' => 'completed', 'paymentStatus' => 'aborted']);
                break;
            }
        }
    }
}

显然,第一个 if 块工作正常,但第二个没有。从 created_at 时间开始 12 分钟后,两者orderStatuspaymentStatus不会更新。

我觉得 for 循环是错误的,但我还没有找到正确的方法。

如何使用 OrderObserver 更新事件实现上述步骤?

标签: phplaravellaravel-5.8

解决方案


I think you are misunderstand what addMinutes method does. created_at attribute is a Carbon object, isn't it? If so, addMinutes just calculate a sum of time and change the value of the attribute. And addSecond does the same, but with seconds.

If you want to have a long-running script you would have to use a sleep call to stop the process for some seconds.

However, the best solution IMO, you should create a cronb job and check every minute if some order is in pending status for 12 minutes, and than change the status.

Take a look at https://laravel.com/docs/5.8/scheduling


推荐阅读