Laravel - 仅同步数据透视表

时间:2017-03-06 12:34:03

标签: php mysql laravel eloquent laravel-5.4

我的数据透视表共包含3列:

  • USER_ID
  • ROLE_ID

组只是一个整数。我希望能够同步用户及其角色,但只能同步属于特定群组的角色。

如果我运行一个简单的同步([1,2,3]),它将从数据透视表中删除所有内容,完全忽略该组。

我有几个解决方案:

选项a:

  1. 为UserRoles创建一个新模型。
  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);
  5. 选项b:

    1. User::roles()->all();
    2. $list_of_desired_ids_for_group_1
    3. 合并$list_of_ids_from_previous_query
    4. User::roles()->sync(list_of_merged_ids);
    5. 还有另一种方法可以用Eloquent做到这一点吗?我认为选项(a)更容易实现,因为我不必合并2个ID和组的多维数组。但是,选项(a)可能更加数据库密集,因为它需要在所有组行上运行DELETE和INSERT。

2 个答案:

答案 0 :(得分:1)

我最终模仿了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]);

答案 1 :(得分:0)

您也可以像这样修改 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);