Laravel - 仅同步枢轴的一个子集 table
Laravel - Sync only a subset of the pivot table
我的数据透视表 table 总共包含 3 列:
- user_id
- role_id
- 组
组只是一个整数。我希望能够同步用户及其角色,但只能同步属于特定组的用户。
如果我 运行 一个简单的同步 ([1,2,3]) 它将从枢轴 table 中删除所有内容,完全忽略该组。
我想到了几个解决方案:
选项a:
- 为 UserRoles 创建一个新模型。
UserRoles::where('group', '=', '1');
User::roles()->detach(list_of_ids_from_previous_query);
User::roles()->attach(list_of_desired_ids_for_group_1);
选项b:
User::roles()->all();
- 花式合并
$list_of_desired_ids_for_group_1
与 $list_of_ids_from_previous_query
User::roles()->sync(list_of_merged_ids);
Eloquent还有其他方法吗?我认为选项 (a) 更容易实现,因为我不必合并 2 个 ID 和组的多维数组。而且,选项 (a) 可能需要更多的数据库密集型,因为它需要 运行 在所有组行上删除和插入。
我最终模仿了 Laravel sync() 方法,但添加了一些额外的过滤。我将该方法添加到我的存储库中,但它可以作为方法添加到模型中。
如果您想将方法移动到模型中,您可以这样做:
/**
* 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]);
您也可以像这样修改 roles
关系:
/**
* @return BelongsToMany
*/
public function roles(): BelongsToMany
{
return $this->belongsToMany(
app(UserRoles::class),
'user_roles',
'user_id',
'role_id'
)->wherePivot('group', 1);
}
然后只使用简单的:
$user->roles()->sync($dataForSync);
我的数据透视表 table 总共包含 3 列:
- user_id
- role_id
- 组
组只是一个整数。我希望能够同步用户及其角色,但只能同步属于特定组的用户。
如果我 运行 一个简单的同步 ([1,2,3]) 它将从枢轴 table 中删除所有内容,完全忽略该组。
我想到了几个解决方案:
选项a:
- 为 UserRoles 创建一个新模型。
UserRoles::where('group', '=', '1');
User::roles()->detach(list_of_ids_from_previous_query);
User::roles()->attach(list_of_desired_ids_for_group_1);
选项b:
User::roles()->all();
- 花式合并
$list_of_desired_ids_for_group_1
与$list_of_ids_from_previous_query
User::roles()->sync(list_of_merged_ids);
Eloquent还有其他方法吗?我认为选项 (a) 更容易实现,因为我不必合并 2 个 ID 和组的多维数组。而且,选项 (a) 可能需要更多的数据库密集型,因为它需要 运行 在所有组行上删除和插入。
我最终模仿了 Laravel sync() 方法,但添加了一些额外的过滤。我将该方法添加到我的存储库中,但它可以作为方法添加到模型中。
如果您想将方法移动到模型中,您可以这样做:
/**
* 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]);
您也可以像这样修改 roles
关系:
/**
* @return BelongsToMany
*/
public function roles(): BelongsToMany
{
return $this->belongsToMany(
app(UserRoles::class),
'user_roles',
'user_id',
'role_id'
)->wherePivot('group', 1);
}
然后只使用简单的:
$user->roles()->sync($dataForSync);