【问题标题】:Laravel - Sync only a subset of the pivot tableLaravel - 仅同步数据透视表的一个子集
【发布时间】:2017-03-06 12:34:02
【问题描述】:

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

  • user_id
  • role_id

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

如果我运行一个简单的 sync([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);

选项 b:

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

Eloquent 还有其他方法可以做到这一点吗?我认为选项 (a) 更容易实现,因为我不必合并 ID 和组的 2 个多维数组。而且,选项 (a) 可能需要更多的数据库密集型,因为它需要在所有组行上运行 DELETE 和 INSERT。

【问题讨论】:

    标签: php mysql laravel eloquent laravel-5.4


    【解决方案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]);
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-06
        • 2018-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-06
        • 1970-01-01
        • 2015-01-27
        相关资源
        最近更新 更多