Eloquent 除了另一个 table 连接之外的递归自连接

Eloquent recursive self join in addition to another table join

首先,标题不太清楚,希望我能在这里解释得更好:

我有一个 MenuItem 模型,它具有递归自连接来表示多级菜单。此外,菜单项实际上可能有一个 Post 模型的外键。模型是这样的:

class MenuItem extends Model
{
    use HasFactory;

    public function parentItem()
    {
        return $this->belongsTo(MenuItem::class, 'parent_menu_id', 'id');
    }

    public function childrenItems()
    {
        return $this->hasMany(MenuItem::class, 'parent_menu_id', 'id');
    }

    public function allChildrenItems()
    {
        return $this->childrenItems()->with('allChildrenItems');
    }

    public function post()
    {
        return $this->belongsTo(Post::class, 'post_id', 'id');
    }

}

为了递归检索所有菜单项,我这样做了并且效果很好:

$menu = MenuItem::with('allChildrenItems')->whereNull('parent_menu_id')->get();

我必须添加条件 whereNull 以首先仅检索顶级菜单项,递归连接将根据层次结构获取其余项。

问题是我还需要用适当的 post 加入每个菜单项。我尝试将上面的 eloquent 查询更新为这样:

$menu = MenuItem::with('allChildrenItems')->whereNull('parent_menu_id')
                ->leftJoin('posts', 'posts.id', '=', 'menu_items.post_id')
                ->get();

但是左连接只适用于顶层 collection whereNull('parent_menu_id'),并且不会在递归连接(children 菜单项)中被拒绝。

如何在此处为 parent 和 children 项添加联接?

在您的 parentItemchildrenItems 关系中,添加 with('post') 以便 post 将添加到每个级别。

public function parentItem()
{
    return $this->belongsTo(MenuItem::class, 'parent_menu_id', 'id')
        ->with('post');
}

public function childrenItems()
{
    return $this->hasMany(MenuItem::class, 'parent_menu_id', 'id')
        ->with('post');
}