Laravel雄辩地带有“ with”和“ wherehas”

时间:2018-07-30 05:52:27

标签: laravel eloquent relationship

比方说,我有与外键链接的三个数据库(播放器,信用和照片):

player
id | name | address

credit
id | player_id | credit_status

photo
id | player_id

说我想让所有拥有credit_status $ status的玩家,我会这样做:

$status = 'bar';
Player::with('photo','credit')->whereHas('credit', function ($q) use ($status) {
            $q->where('credit_status', $status)->with('credit_status');
        })->paginate(15);

这将列出所有具有credit_status $ credit的玩家,但仍然列出该玩家的所有积分,而不管其状态如何。

输出类似于:

{
id: 1
name: Andrew
address: home
photo: {
          id: 2
          photo: image1
       }
credit: {
          [
              {
              id: 6
              credit_status: foo,
              id: 2
              credit_status: bar
              }
          ]
        }
},
{
id: 2
name: Mark
address: home
photo: {
          id: 5
          photo: image4
       }
credit: {
          [
              {
              id: 10
              credit_status: foo,
              id: 6
              credit_status: bar,
              id: 8
              credit_status: bar
              }
          ]
        }
}

我也想用('credit')过滤信用。 我想要的输出:

{
id: 1
name: Andrew
address: home
photo: {
          id: 2
          photo: image1
       }
credit: {
          [
              {
              id: 2
              credit_status: bar
              }
          ]
        }
},
{
id: 2
name: Mark
address: home
photo: {
          id: 5
          photo: image4
       }
credit: {
          [
              {
              id: 6
              credit_status: bar,
              id: 8
              credit_status: bar
              }
          ]
        }
}

3 个答案:

答案 0 :(得分:4)

您可以对with进行相同的过滤(限制急切的加载):

$creditFilter = function ($q) use ($status) {
    $q->where('credit_status', $status);
};

Player::with(['photo', 'credit' => $creditFilter])
    ->whereHas('credit', $creditFilter)
    ->paginate(15);

您可以保存该闭包并将其传递到withwhereHas,这样您就不必两次键入相同的闭包。

Laravel 5.6 Docs - Eloquent - Relationships - Eager Loading - Constraining Eager Loads

答案 1 :(得分:2)

如果您也想过滤信用,则还必须使用credit中的条件。实际上,whereHas()with()是独立工作的,它们并不相互依赖。

 $status = 'bar';
    Player::with(['photo','credit' => function($query) use ($status){

          $query->where('credit_status', $status)->with('credit_status');


    }])->whereHas('credit', function ($q) use ($status) {
                $q->where('credit_status', $status)->with('credit_status');
            })->paginate(15);

答案 2 :(得分:0)

You only need to make conditional with the 'with' function; not with the 'whereHas' function. 

$creditFilter = function ($q) use ($status) {
    $q->where('credit_status', $status);
};

Player::with(['photo', 'credit'])
    ->with(['credit' => $creditFilter])
    ->paginate(15);