Laravel 获取BelongToMany关系中根类别ID下的所有页面
这是我在过去几个小时里试图解决的一个挑战 我有一个Laravel 获取BelongToMany关系中根类别ID下的所有页面,laravel,eloquent,Laravel,Eloquent,这是我在过去几个小时里试图解决的一个挑战 我有一个页面模型和一个类别模型 一个页面可以位于多个类别下,每个类别可以有多个页面,因此它们之间存在多对多关系 最重要的是,每个类别都有一个父类别,因此每个类别之间有一对多 因此,考虑到所有这些,以下是模型: 页面模式 // table ['id', 'title', 'content', 'created_at', ...] class Page extends Model { public function categories()
页面
模型和一个类别
模型
一个页面可以位于多个类别下,每个类别可以有多个页面,因此它们之间存在多对多关系
最重要的是,每个类别都有一个父类别,因此每个类别之间有一对多
因此,考虑到所有这些,以下是模型:
页面模式
// table ['id', 'title', 'content', 'created_at', ...]
class Page extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
// table ['id', 'category_id', 'name', 'created_at', ...]
class Category extends Model
{
public function pages()
{
return $this->belongsToMany(Page::class)
}
public function categories()
{
return $this->hasMany(Category::class);
}
public function parent()
{
return $this->belongsTo(Category::class, 'category_id');
}
}
类别模型
// table ['id', 'title', 'content', 'created_at', ...]
class Page extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
// table ['id', 'category_id', 'name', 'created_at', ...]
class Category extends Model
{
public function pages()
{
return $this->belongsToMany(Page::class)
}
public function categories()
{
return $this->hasMany(Category::class);
}
public function parent()
{
return $this->belongsTo(Category::class, 'category_id');
}
}
我确实有一个category\u页面
表,其中包含category\u id
和page\u id
,以链接该关系
现在是棘手的部分
我试图创建一个有说服力的查询,给定一个category\u id
,我就能得到这个类别下的所有页面以及这个类别的子类别下的所有页面
我可能可以通过嵌套SQL查询中的多个连接或简单的foreach
循环递归地获取子页面来实现这一点(但这将花费大量不必要的时间)
有什么好的优雅的方法吗
提前谢谢
编辑:
在Laravel中有一种方法可以实现递归关系,并将所有子类别与页面放在一行代码中
//类别内模型
public function childrenCategories()
{
return $this->hasMany(Category::class)->with('childrenCategories');
}
现在我可以做了
Category::whereId($rootCategoryId)->with('childrenCategories')->first();
这样,我将有一个所有类别的嵌套树,然后我可以加载到它的页面关系,我就完成了
但是,它有一个巨大的问题,它执行的查询量非常大(每个嵌套级别都有一个查询),在生产应用程序中使用它是没有意义的。
所以我有一个解决方案,它很糟糕,所以我愿意接受其他建议。如果您使用的是id,您可以使用嵌套的
whereHas()
:
如果使用模型,则有两个选项:
1) 嵌套的whereHas()
方法:
$pages = Page
::whereHas('categories', function ($query) use ($category) {
$query
->where('id', $category->id)
->orWhereHas('parent', function ($query) use ($category) {
$query->where('id', $category->id);
});
})
->get();
2) 收集当前类别id及其子类别id,然后使用一个whereHas()
方法
$categoryIds = $category->categories->pluck('id')->push($category->id);
$pages = Page
::whereHas('categories', function ($query) use ($categoryIds) {
$query->whereIn('categories.id', $categoryIds);
})
->get();
更多信息:感谢您的快速回复,您的查询看起来只会让我降低一级(类别->页面和子类别->页面)。如果我想从当前的类别ID(有时可能是3-4个级别)一直往下看,这是行不通的。我说得对吗?是的,你说得对。您的表结构对此无效。您应该了解嵌套集技术(laravel-)中的良好实现。它允许您在一个查询中获取所有子类,然后通过第二个查询为它们获取页面。