Laravel Eloquent: 按加载的model.property对结果进行排序,并对结果进行分页

Laravel Eloquent: Order results by eaged loaded model.property, and paginate the result

假设我有三个模型:PostCategoryTag

Post belongsTo 分类和分类 hasMany Post.

TagCategory 之间存在 manyToMany 关系。

我想按类别名称列出我的帖子并对结果进行分页。

Post::with('category','category.tags')
  ->orderBy('category.name') //this is the bogus line
  ->paginate(10);

但是这个语法不起作用。


我试过的是 this 为:

Post::select('categories.*')
  ->join('categories','posts.category_id','=','categories.id')
  ->orderBy('categories.name)
  ->paginate(10);

但是我丢失了急切加载的数据。

如果我删除 select() 子句,那么我会得到垃圾数据,因为 categories.id 会覆盖 posts.id。参见 here


有什么优雅的方法可以解决这个问题吗? 在这上面花了几个小时之后,我距离遍历分页帖子和 'manually' 加载关系仅一步之遥:

foreach($posts as $post) {
  $post->load('category','category.tags');
}

甚至不确定这是否有缺点,但它似乎不对。如有错误请指正

更新最后一步:急切加载分页结果将不起作用,所以如果我走那条路,我将需要实施更丑陋的修复。

您应该可以同时使用 joinwith

Post::select('posts.*') // select the posts table fields here, not categories
->with('category','category.tags')
->join('categories','posts.category_id','=','categories.id')
->orderBy('categories.name)
->paginate(10);

请记住,with 子句不会改变您的查询。只有查询执行后,才会收集n+1个关系。

您的解决方法确实失去了预先加载的好处。但是你也可以在collection/paginator(查询结果)上调用load(..),所以调用->paginate(10)->load('category','category.tags')等同于上面的查询。