My pivot table contains a total of 3 columns:
Group is just an integer. I would like to be able to sync the users and their roles but only the ones that belong to a specific group.
If I run a simple sync([1,2,3]) it will remove everything from the pivot table, ignoring the group altogether.
I have a few solutions in mind:
Option a:
UserRoles::where('group', '=', '1');
User::roles()->detach(list_of_ids_from_previous_query);
User::roles()->attach(list_of_desired_ids_for_group_1);
Option b:
User::roles()->all();
$list_of_desired_ids_for_group_1
with $list_of_ids_from_previous_query
User::roles()->sync(list_of_merged_ids);
Is there another way to do this with Eloquent? I reckon option (a) is easier to implement as I don't have to merge 2 multidimensional arrays of IDs and groups. But also, option (a) might be more database intensive as it needs to run a DELETE and INSERT on all group rows.
I ended up mimicking the Laravel sync() method but added some additional filtering. I added the method to my Repository, but it could be added as a method to a Model.
If you want to move the method to a model, you could do something like this:
/**
* 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;
}
Usage:
$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]);
You also could have just modified the roles
relation like this:
/**
* @return BelongsToMany
*/
public function roles(): BelongsToMany
{
return $this->belongsToMany(
app(UserRoles::class),
'user_roles',
'user_id',
'role_id'
)->wherePivot('group', 1);
}
and then just used simple:
$user->roles()->sync($dataForSync);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.