尝试分派作业时不允许序列化“关闭”

问题描述 投票:0回答:1

我是 php 和 laravel 的新手,我试图在创建一个模型时分派一项作业,但是 当我尝试分派该作业时,我收到错误“不允许序列化‘闭包’” ,这让我感到困惑,因为我认为我需要传入一个匿名函数才能得到该错误。

我有一个观察者来监视我的订单模型创建的事件。

<?php

namespace App\Observers;

use App\Models\Order;
use App\Jobs\CreateOrderTasks;

class OrderObserver
{
    /**
     * Handle the Order "created" event.
     */
    public function created(Order $order): void
    {
        CreateOrderTasks::dispatch($order);
    }
    ...etc

}

我有我的工作

    <?php
    
    namespace App\Jobs;
    
    use Illuminate\Contracts\Queue\ShouldQueue;
    use Illuminate\Foundation\Queue\Queueable;
    use App\Models\Order;
    use Illuminate\Foundation\Bus\Dispatchable;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Support\Facades\Log;
    
    class CreateOrderTasks implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    
        protected Order $order;
    
        public function __construct(Order $order)
        {
            $this->order = $order;
        }
    
        /**
         * Execute the job.
         */
        public function handle(): void
        {
                Log::info('Order retrieved:', ['order' => $this->order]); // Log the order details
        }
    }

我还尝试过仅传递订单 ID 并更新作业,例如

CreateOrderTasks::dispatch($order->id);

但我仍然遇到同样的错误。我做错了什么?

php laravel eloquent laravel-8 laravel-queue
1个回答
0
投票

当正在序列化的数据中存在无法序列化的内容(例如闭包、资源或其他一些不可序列化的内容)时,Laravel 中经常会出现您遇到的错误“不允许序列化‘Closure’”数据结构。就您而言,由于您正在使用 Eloquent 模型调度作业,因此您应该验证并考虑以下几点来解决此问题:

1. 确保模型可序列化

您使用的

SerializesModels
特征旨在处理 Eloquent 模型的序列化。它在序列化之前将模型转换为其主键,然后在处理作业时从数据库重新检索它们。但是,有一些注意事项:

  • 卸载的关系:确保模型实例中不存在可能导致序列化期间出现问题的卸载关系或闭包。如果您的
    $order
    模型有任何未加载的关系,它们可能无法正确序列化。

2. 检查模型属性

确保模型中没有不可序列化的属性。闭包、流或资源等属性无法序列化。

3. 改为传递型号 ID

如果您仍然遇到问题,仅传递模型 ID 是一种安全的方法。但是,请确保您随后在作业的

handle
方法中检索模型:

// In your observer
public function created(Order $order): void
{
    CreateOrderTasks::dispatch($order->id);
}

// In your job
use App\Models\Order;

public function __construct(int $orderId)
{
    $this->orderId = $orderId;
}

public function handle(): void
{
    $order = Order::find($this->orderId);

    if ($order) {
        Log::info('Order retrieved:', ['order' => $order->toArray()]);
    } else {
        Log::warning('Order not found:', ['orderId' => $this->orderId]);
    }
}

4. 检查中间件或事件监听器

有时,中间件或事件监听器可能使用闭包或不可序列化的数据。确保没有中间件或事件侦听器使用可能间接导致问题的闭包。

5. 调试

为了更好地了解可能导致序列化问题的原因,您可以:

  • 记录订单数据:在调度作业之前,记录订单数据以确保一切符合预期。
  • 检查队列配置:确保您的队列驱动程序(例如数据库、Redis)设置正确,因为错误配置可能会导致意外错误。

6. 确保正确的队列设置

确保您的队列系统配置正确。例如,如果您使用数据库队列,请确保迁移是最新的并且数据库设置正确。

结论

该错误通常是由于尝试序列化 PHP 无法序列化的内容而引起的。通过确保模型配置正确、仅传递必要的数据并检查任何闭包或不可序列化的属性,您应该能够解决此问题。如果您仍然遇到问题,请考虑查看 Laravel 关于队列和作业的文档以获取更多见解,或咨询 Laravel 社区论坛以获取更细致的调试技巧。

© www.soinside.com 2019 - 2024. All rights reserved.