首页 文章

Laravel排队作业如何处理已删除的模型作为输入?

提问于
浏览
1

如果Laravel排队作业作为输入传递了Eloquent模型,但是在作业在队列中运行之前删除了模型会发生什么?

例如,我正在使用Laravel 5.2构建电子商务网站,客户可以在其中输入地址和付款方式 . 付款方式属于地址 . 但是,如果客户试图删除地址,而不是级联并删除与之关联的任何付款方式,我会通过将其标记为已禁用来软删除该地址 . 这样,在客户更新与其关联的帐单地址之前,仍然可以使用付款方式 .

但是,如果支付方法被删除并且它引用了已被软删除的地址,我想做一些垃圾收集并从数据库中删除该地址 . 这不需要同步发生,因此我编写了一个简单的可排队作业来完成此任务 . handle方法如下所示:

public function handle(PaymentMethodRepository $paymentMethodRepository, AddressRepository $addressRepository)
{
    $billingAddress = $paymentMethodRepository->address($this->paymentMethod);

    if ( ! $billingAddress->enabled) {
        $addressRepository->delete($billingAddress);
    }
}

我在PaymentMethodsController的 destroy 方法中调度此作业 . 但是,如果在队列中执行作业之前从数据库中删除了传递给作业的付款方法,那么作业是否会失败?

我还在开发这个网站,所以我没有服务器来部署和测试会发生什么 . 我知道模型被序列化以放入队列中,但我想知道在恢复模型以执行作业时是否会出现问题 .

1 回答

  • 0

    是的,如果在执行作业之前删除“序列化模型”,则作业将失败 . 该模型并未真正序列化 - 作业存储模型类和模型标识符,并在执行前获取模型 .

    要解决此问题,您可以将模型的主键存储在作业中,然后在执行作业时检查记录是否存在:

    class DeleteAddressJob extends Job implements ShouldQueue
    {
        private $addressId;
    
        public function __construct(int $addressId)
        {
            $this->addressId = $addressId;
        }
    
        public function handle(AddressRepository $addressRepository)
        {
            $address = $addressRepository->find($this->addressId);
    
            if (is_null($address)) {
                // Address doesn't exist. Complete job...
                return;
            }
    
            // Delete the address...
        }
    }
    

相关问题