若把Model传递到队列中,model对应的relations 并不会被序列化,想知道为什么

1. 运行环境

1). 当前使用的 Laravel 版本?

Laravel Framework 8.83.27

2). 当前使用的 php/php-fpm 版本?

PHP 版本:7.4

3). 当前系统

win10

4). 业务环境

开发环境

2. 问题描述?

若把model传递到队列中,model对应的relations 并不会被序列化

//Model Item
class  Item  extends  Model
{
    public  function  category()
    {
        return  $this->belongsTo(Category::class, 'cate_id');
    }
}

// 放入队列想相关代码
$query = Item::query()->with(['category:id,parent_ids']);
$item = $query->find(1);
$job = new ImportItemJob($item);
dispatch($job);

// Job类
class  ImportItemJob  implements  ShouldQueue
{
   use  Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
   public  function  __construct($item)
   {
       $this->item = $item;
   }
   public  function  handle()
   {
      dump($this->item->category)
  }
 }

3. 您期望得到的结果?

4. 您实际得到的结果?

在 job类中 $this->item->category 会重新从数据库查询一次
想知道 laravel这么设计的原因是什么,有没有什么方法,不让category在重新查询一次

提问的过程 搜到了一些资料

dev.to/ryancco/understanding-larav...
原因在于

When complicated objects are serialized, their string representations can be atrociously long, taking up unnecessary resources both on the queue and application servers.

当复杂的objects 被序列化的时候,生产的字符出会过长,浪费不必要的资源

所以SerializesModels这个 trait 就用来解决这个问题,只 存储 Model 类 路径和主键等信息

所以想知道 什么序列化的方法 能类似 SerializesModels 的作用,同时又不用 从数据库查询吗?

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 8

把Model转为普通class或者array,传入Job

1年前 评论

没必要吧,不仅 relations 要查库,model 也要查库的,这样也有个好处,获得的数据是最新的

1年前 评论
ksc (楼主) 1年前

把整个model对象放到队列里本身就是错误的做法。

会在查询因为是动态的,你只要没有访问关联对象的属性,就不会触发查询。

1年前 评论

先不说其他的,单说你搜到的资料说的很明白了,为什么会用s这些替代,以及提到了关系的时候,避免字符串过长等,是为了什么。

你需要不查数据库,存着这些数据,然后直接用,会造成什么后果,你搜到的资料讲的很清楚,这不是一种消耗资源?你都不纠结这个消耗了,那还纠结什么查几次sql的事情了。

并不是只有优化sql才叫优化

1年前 评论
ksc (楼主) 1年前
jackyyrose 1年前

是的,就是SerializesModels 搞得鬼。 你可以不使用SerializesModels, 把它从use里面去掉,这样整个带关系的model数据就会被一起序列化了。对于load关系超多,字段超多的model会增加资源消耗。你这个例子因为对象不算大,可以用这个方法。

对于数据大关系多的model,一般use SerializesModels(这样只序列化model id),并且在handle()里面用Item::query()->with(['xxx',‘yyy’'])查询一次就可得到所有关系。

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!