Laravel如何为主查询的每条文章获取两条同表随机关联文章?
实现方法
这里提供几种在Laravel中为查询到的文章追加随机关联文章的方案,你可以根据业务场景选择:
方案一:遍历文章追加关联(简单直接)
先查询主文章列表,再逐个为每篇文章查询2条排除自身的随机关联文章:
// 查询主文章列表 $articles = Article::orderBy('created_at', 'DESC') ->skip($start) ->take($length) ->get(['id', 'title', 'content', 'created_at']); // 为每篇文章追加随机关联文章 $articles->each(function ($article) { $article->related = Article::where('id', '!=', $article->id) ->inRandomOrder() ->take(2) ->get(['id', 'title', 'content', 'created_at']); }); // 返回JSON格式结果 return response()->json($articles);
优缺点:实现简单,无需修改模型;但会产生N+1查询(N为主文章数量),如果主文章数量较多,会影响数据库性能。
方案二:利用Eloquent关联预加载
先在Article模型中定义获取随机关联文章的方法,再通过预加载方式获取:
1. 在模型中定义关联方法
// app/Models/Article.php public function relatedArticles() { return $this->hasMany(Article::class) ->where('id', '!=', $this->id) // 排除当前文章自身 ->inRandomOrder() ->take(2); }
2. 查询时加载关联
$articles = Article::orderBy('created_at', 'DESC') ->skip($start) ->take($length) ->with('relatedArticles') // 预加载关联 ->get(['id', 'title', 'content', 'created_at']); // 重命名关联字段为`related`(匹配你需要的返回格式) $articles->each(function ($article) { $article->related = $article->relatedArticles; unset($article->relatedArticles); }); return response()->json($articles);
优缺点:代码更符合Eloquent规范;但同样存在N+1查询问题,适合主文章数量较少的场景。
方案三:批量查询优化性能
如果主文章数量较多,建议用批量查询减少数据库请求次数:
// 查询主文章列表 $articles = Article::orderBy('created_at', 'DESC') ->skip($start) ->take($length) ->get(['id', 'title', 'content', 'created_at']); // 获取所有主文章ID,用于排除自身 $mainArticleIds = $articles->pluck('id')->toArray(); // 批量查询足够数量的随机文章(按主文章数*2准备,可根据实际调整) $allRelatedArticles = Article::whereNotIn('id', $mainArticleIds) ->inRandomOrder() ->take(count($mainArticleIds) * 2) ->get(['id', 'title', 'content', 'created_at']); // 为每篇主文章分配2条随机关联文章 $articles->each(function ($article) use ($allRelatedArticles) { $article->related = $allRelatedArticles->random(2); }); return response()->json($articles);
优缺点:仅产生2次数据库查询,性能大幅提升;但不同主文章的关联文章可能出现重复,如果需要完全避免重复,可以在分配后移除已使用的文章(需注意文章总数是否足够)。
内容的提问来源于stack exchange,提问作者Ostet
相关产品推荐
相关产品推荐

