2017-03-06 90 views
1

我的透視表含有總共3米欄:Laravel - 僅同步樞軸表的子集

  • USER_ID
  • ROLE_ID

組僅僅是一個整數。我希望能夠同步用戶和他們的角色,但僅限於屬於特定組的用戶。

如果我運行一個簡單的同步([1,2,3]),它將從數據透視表中刪除所有內容,完全忽略該組。

我腦子裏有幾個解決方案:

選項一:

  1. 創建一個的UserRole新模式。
  2. UserRoles::where('group', '=', '1');
  3. User::roles()->detach(list_of_ids_from_previous_query);
  4. User::roles()->attach(list_of_desired_ids_for_group_1);

選項B:

  1. User::roles()->all();
  2. 花哨$list_of_ids_from_previous_query
  3. User::roles()->sync(list_of_merged_ids);合併$list_of_desired_ids_for_group_1

有沒有另一種方法來做到這一點與雄辯?我認爲選項(a)更容易實現,因爲我不必合併2個ID和組的多維數組。而且,選項(a)可能需要更多的數據庫,因爲它需要在所有組行上運行DELETE和INSERT。

回答

1

我最終模仿Laravel sync()方法,但添加了一些額外的過濾。我將該方法添加到了我的Repository中,但它可以作爲方法添加到Model中。

如果你想的方法轉移到一個模型,你可以做這樣的事情:

/** 
* Simulates the behaviour of Eloquent sync() but 
* only on a specific subset of the pivot 
* @param integer $group 
* @param array $roles 
* @return Model 
*/ 
public function syncBy($group, array $roles) 
{ 
    // $this is the User model for example 
    $current = $this->roles->filter(function($role) use ($group) { 
     return $role->pivot->group === $group; 
    })->pluck('id'); 

    $detach = $current->diff($roles)->all(); 

    $attach_ids = collect($roles)->diff($current)->all(); 
    $atach_pivot = array_fill(0, count($attach_ids), ['group' => $group]); 
    $attach = array_combine($attach_ids, $atach_pivot); 

    $this->roles()->detach($detach); 
    $this->roles()->attach($attach); 

    return $this; 
} 

用法:

$user= App\User::find(1); 
// Will sync for user 1, the roles 5, 6, 9 but only within group 3 
$user->syncBy(3, [5, 6, 9]);