查询远距离关系

时间:2019-03-31 20:41:47

标签: laravel foreach eloquent

我有三个表:usersaccountshotels.用户和帐户通过belongstoMany关系连接,而帐户和酒店以相同方式连接。每个用户都有一个帐户,而那些帐户有一个酒店。

当我有Auth::user(),后如何退还所有酒店?

$accounts = Auth::user()->accounts()->get();

使用上述声明,我可以获得所有帐户。如何退回所有酒店?

我尝试了什么?

public function index(Request $request)
    {
        $accounts = Auth::user()->accounts()->get();
        $hotels = collect();
        foreach ($accounts as $key => $a) {

            $h = $a->hotels();
            $hotels = $hotels->toBase()->merge($h);

                }
            dd($hotels);
        return view('hotels.index',compact('hotels'));

    }

但是此代码不会返回我可在刀片视图文件中使用的酒店集合

1 个答案:

答案 0 :(得分:3)

案例1

如果您具有如下图所示的关系

user accounts hotels relationship

您正在寻找的是hasManyThrough关系。

Laravel documentation

  

“具有多次通过”关系为通过中间关系访问遥远关系提供了方便的快捷方式

在您的情况下,您可以在用户模型上定义关系

public function hotels()
{
  return $this->hasManyThrough('App\Hotel', 'App\Account');
}

要获取您的酒店集合,您只需使用

$hotels = Auth::user()->hotels;

您还可以为hasManyThrough函数提供额外的参数,以定义在每个表上使用的键,上面链接的文档中提供了很好的示例!

案例2

如果相反,您具有下图所示的关系

distant many-to-many relation

这比较棘手(或者至少不太干净)。我能想到的使用最少查询的最佳解决方案是使用with

$accounts = Auth::user()->accounts()->with('hotels')->get();

将为您提供一个帐户集合,每个帐户都有一个hotels子帐户。现在,我们要做的就是将酒店作为一个独立的集合,这很简单,并且具有Laravel提供的一些整洁的集合功能。

$hotels = $accounts->flatMap(function($account) {
  return $account->hotels;
})->unique(function ($hotel) {
  return $hotel->id;
});

这将完成创建酒店集合的工作。我认为, 简单地建立新的关系会更清洁,更有效 ,如下所示。

a simpler many-to-many relationship

然后使用基本的Eloquent方法执行查询。