2015-11-06 15 views
1

這是通過人工獲取的數據作爲一個數組,然後repassing它:如何在Eloquent子查詢中使用自定義查詢範圍?

public function scopeWhereWhitelisted($query, $value=true, Tenant $tenant) 
{ 
    return $query->where(function($query)use($value,$tenant) 
    { 
     $user_id_list = $tenant->getWhiteListedUsersGroup() 
               ->users() 
               ->select('users.id') 
               ->lists('id') 
               ->all() 
     ; 

     $query->{ $value ? 'whereIn' : 'whereNotIn' }('users.id',$user_id_list); 
    }); 
} 

但我想這個工作(註釋//表示唯一的區別):

public function scopeWhereWhitelisted($query, $value=true, Tenant $tenant) 
{ 
    return $query->where(function($query)use($value,$tenant) 
    { 
     $user_id_list = $tenant->getWhiteListedUsersGroup() 
               ->users() 
               ->select('users.id') 
               //->lists('id') 
               //->all() 
     ; 

     $user_id_list = $tenant->getWhiteListedUsersGroup()->users()->select('users.id');//->lists('id')->all(); 
     $query->{ $value ? 'whereIn' : 'whereNotIn' }('users.id',$user_id_list); 
    }); 
} 

我想成爲能夠創建一個「真正的」子查詢,而不必爲每個範圍提供自定義查詢範圍和關係查詢的重複副本。 $tenant->getWhiteListedUsersGroup()->users()是許多一對多的關係

這裏是什麼工作要做,以獲得真正的子查詢的例子:

public function scopeWhereWhitelisted($query, $value=true, Tenant $tenant) 
{ 
    return $query->where(function($query)use($value,$tenant) 
    { 
     $query->{ $value ? 'whereIn' : 'whereNotIn' }('users.id',function($query) 
     { 
      $query->from('groups_memberships') 
        //  recreating an existing relationship function 
        ->join('groups','groups.id','group_memberships.group_id') 
        ->select('users.id') 
        //  recreating an already existing query scope 
        ->whereNull('deleted_at') 
      ; 
     }); 
    }); 
} 
  • 這個問題很可能會同時適用於Laravel 4.0+和5.0+
  • 這個問題未回答How to do this in Laravel, subquery where in
  • 重構代碼以便查詢從預期的子查詢開始,只要我需要第二個非平凡的子查詢就不會工作。
  • 列入/排除->getQuery()並沒有區別。
  • 我必須在假的子選擇或非DRY自定義查詢範圍之間進行選擇。
  • 看來主要的問題是子選擇引擎迫使我使用不能從現有關係初始化的預先存在的$query對象。
  • 軟刪除的重新創建(whereNull('deleted_at'))是一個簡單的例子,但我可能必須重新創建一個可能相對複雜的queryscope。

回答

0

這是你最喜歡的嗎?

$value; //true or false 

$tenant->whereHas('user', function($query) use ($value){ 
    $query->whereHas('groupMembership', function($query) use ($value){ 
     $query->whereHas('group', function($query) use ($value){ 
      if($value){ $query->onlyTrashed();) 
     }); 
    }) 
}) 

這假定該組關係包括在關係

+0

'一個withTrashed()調用whereHas'是嚴格假表。每個'whereHas'都爲每個表格計算一個臨時列。這意味着索引不能使用,並且會有全表掃描。你有三個'whereHas'嵌套,這意味着對於用戶表中的每一行,MySQL必須計算「has groupMembership」tmp列。要確定,groupMember的每個全表掃描都將執行組的全表掃描。這基本上是指數增長的全表掃描的3層。 https://github.com/laravel/framework/issues/3543 – InstanceOfMichael