若把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 的作用,同时又不用 从数据库查询吗?
把Model转为普通class或者array,传入Job
没必要吧,不仅 relations 要查库,model 也要查库的,这样也有个好处,获得的数据是最新的
把整个model对象放到队列里本身就是错误的做法。
会在查询因为是动态的,你只要没有访问关联对象的属性,就不会触发查询。
先不说其他的,单说你搜到的资料说的很明白了,为什么会用
s
这些替代,以及提到了关系的时候,避免字符串过长等,是为了什么。你需要不查数据库,存着这些数据,然后直接用,会造成什么后果,你搜到的资料讲的很清楚,这不是一种消耗资源?你都不纠结这个消耗了,那还纠结什么查几次sql的事情了。
并不是只有优化sql才叫
优化
是的,就是SerializesModels 搞得鬼。 你可以不使用SerializesModels, 把它从use里面去掉,这样整个带关系的model数据就会被一起序列化了。对于load关系超多,字段超多的model会增加资源消耗。你这个例子因为对象不算大,可以用这个方法。
对于数据大关系多的model,一般use SerializesModels(这样只序列化model id),并且在handle()里面用Item::query()->with(['xxx',‘yyy’'])查询一次就可得到所有关系。