我必须在多个页面上显示帖子,但我希望订单始终不同。不幸的是,inRandomOrder()
可以通过请求其他页面来提供已显示的项目,orderBy(DB::raw('RAND(aseed)')
或orderByRaw('RAND(aseed)')
(会话常量aseed
)是特定于数据库的,并且在大数据集上速度较慢。
我决定缓存包含要显示的帖子的ID的数组,然后将其洗牌并检索它以进行分页。
修补程序中的一个简单示例:
>>>$posts_ids = Post::pluck('id')->shuffle();
=> Illuminate\Support\Collection {#835
all: [
8,
6,
1,
2,
4,
7,
3,
5,
],
}
>>>$sliced_ids = $posts_ids->slice(0,2)->all();
=> [
8,
6,
]
>>> Post::whereIn('id',$posts_ids->slice(0,2)->all())->get();
=> Illuminate\Database\Eloquent\Collection {#865
all: [
App\Post {#883
id: 6,
...
},
App\Post {#881
id: 8,
...
}
],
}
whereIn
(也是findMany
)方法返回的帖子按升序排列,原因是使用where子句...WHERE id IN (6,8)
。一个解决方案可能是orderByRaw('FIELD(id,$sliced_ids)
,但是
同样适用于orderByRaw('RAND(aseed)')
...
是否有一种有效的方法可以在页面间使用一致的随机顺序进行分页?
编辑:解决方案
我正在探索使用inRandomOrder
的可能性,缓存Eloquent Collection并重建它。类似的东西:
$posts = Cache::remember('posts', 30, function(){
return serialize(Post::with('terms')->inRandomOrder()->get());
});
$posts = unserialize($posts);
在这种情况下,我认为最好使用if (Cache::has('key')){...}
修改
我不知道它是否可以依赖于redis连接类型:在tcp上我必须序列化和反序列化,而在unix socket上它可以工作而不需要序列化/反序列化