【问题标题】:Laravel doesn't load relationship for serialized modelLaravel 不为序列化模型加载关系
【发布时间】:2025-12-31 00:20:12
【问题描述】:

我有一份简单的工作:

class SampleJob extends Job implements ShouldQueue
{
    use InteractsWithQueue, SerializesModels, DispatchesJobs;

    private $customer;

    public function __construct(Customer $customer)
    {
        parent::__construct();

        $this->customer = $customer;
    }

    public function handle()
    {
        doSomeStuff($customer->currency());
    }
}

Customer 模型中,我与country 有关系:

clas Customer extends Model
{
    public function country()
    {
        return $this->belongsTo(Country::class);
    }

    public function currency()
    {
       return $this->country->currency();
    }
}

当我通过 dispatch(new SampleJob($customer)) 发送作业时,我在日志中收到错误:

 Call to a member function currency() on null {"code":0,"file":"Customer.php","line":386} 

这里有一个棘手的问题是,如果我从工作中删除 SerializesModels 特征,它会正常工作。但我真的不想这样做,因为它会导致无法预料的错误(我们有很多这样的工作,还有更多的属性)。

所以我只想弄清楚为什么会发生这个错误。

我使用database 驱动程序来工作。

Laravel 5.8.16。此外,使用 Laravel 5.6 也可以正常工作。

【问题讨论】:

    标签: php laravel


    【解决方案1】:

    建议在序列化时避免传递对象。在这种情况下,传递客户 ID 会更好:

    class SampleJob extends Job implements ShouldQueue
    {
        use InteractsWithQueue, SerializesModels, DispatchesJobs;
    
        private $customerId;
    
        public function __construct(int $customerId)
        {
            parent::__construct();
    
            $this->customerId = $customerId;
        }
    
        public function handle()
        {
            $customer = Customer::find($this->customerId);
    
            doSomeStuff($customer->currency());
        }
    }
    

    【讨论】:

    • 是的,我知道这一点。但该项目是一种遗产,我不确定我们是否有时间将所有工作重构为这种方法。所以我想先弄清楚当前的错误
    【解决方案2】:

    Laravel 不为序列化模型加载关系是一件好事。 大多数情况下,它可以让您远离Segmentation fault (core dumped)

    但是使用SerializesModels是不够的,你还应该使用一个函数->withoutRelations()

    像这样:

    public function __construct(Sale $sale)
    {
        $this->sale         = $sale->withoutRelations();
    ...
    

    但是如果您忘记了withoutRelations() 功能,系统将Serialize 您的对象链接在您UnSerialize 您的数据返回后将丢失。这会导致消息

    Segmentation fault (core dumped)
    

    【讨论】: