【问题标题】:Laravel Eloquent filter relationship by last pivot recordLaravel Eloquent 过滤器关系按最后一个数据透视记录
【发布时间】:2017-02-28 20:32:54
【问题描述】:

我有 3 个表:userrole 和 pivot user_role。用户和角色之间存在多对多的关系。

还有一个细节,每个分配(用户角色)在user_role 表中都有timestamp,所以我可以找到最近为用户添加的角色。

是否有可能编写一个雄辩的查询来获取所有最近分配角色的用户,例如 id = 5?

我需要以某种方式从pivot 获取由timestamp 排序的最后一条记录,然后在whereHas 语句中使用它。但是如何获得最后一条记录呢?

编辑

感谢您的回答。但我想让这一切变得更复杂一些。如果我们添加表system,现在systemuser之间将是一对多的关系,所以用户可以属于一个系统,系统可以有多个用户。

现在,如何获得例如system 的 id,其中包含最后一个角色 id = 5 的用户(与开头一样)。

【问题讨论】:

    标签: php mysql laravel orm eloquent


    【解决方案1】:

    首先,您需要确保您的关系包含数据透视时间戳:

    public function users()
    {
        return $this->belongsToMany('User')->withTimestamps();
    }
    

    然后您可以在代码中使用以下查询来获取最近获得特定角色(例如 id=5)的所有用户。

    $role = Role::with(['users', function($query) {
        $query->orderBy('pivot_created_at', 'DESC');
    }])->find(5);
    
    // all users with (role_id = 5) ordered by (user_role.created_at DESC)
    $users = $role->users;
    

    【讨论】:

      【解决方案2】:

      您可以向关系中添加数据透视列,如下所示:

      /**
       * The roles that belong to the user.
       */
      public function roles()
      {
          return $this->belongsToMany('App\Role')->withPivot('timestamp');
      }
      

      如果你想检查用户最近是否有特定的角色,我会这样做

      public function hasRecentRole($roleId, $howRecently = 'last week')
      {
           return $this->roles()->where('id', $roleId)->wherePivot('timestamp', '>', new Carbon\Carbon($howRecently))->count();
      }
      

      编辑:试试这样的。

      $systems = System::whereHas('users', function ($query) {
          $query->whereHas('roles', function ($query) {
              $query->where('id', 5)
                  ->whereRaw('timestamp = (select max(`timestamp`) from user_roles WHERE user_id = role_user.user_id'));
          });
      })->get();
      

      如果不是,也许您应该分步进行。就像获取具有最新角色 5 的用户,然后获取至少具有这些用户之一的系统。

      【讨论】:

      • 是否有可能从模型中的方法中按时间戳排序的数据透视表中获取最后一条记录?所以我将能够做到这一点:System::('users.lastRole, function($q){...})。它对我有用,但现在我有了“users.roles”,它为我提供了我可以通过关闭查询的所有角色,但我现在只需要拥有“users.lastRole”。
      【解决方案3】:

      这给出了user_role 表中按timestamp 列排序的最后一个用户。

      $user->roles()->withPivot('timestamp')->orderBy('user_role.timestamp','desc')->first();
      

      更新:

      $users=User::with(['system','role'=>function($query)
      {
         $query->orderBy('pivot_timestamps','desc');
      }])->get();
      

      然后,这将给出所有用户的系统 ID,按数据透视表中的时间戳排序。

      foreach($users as $user)
      {
            $user->system->id;
      }
      

      确保您在用户和角色模型withPivot. 中有关系,以便您可以使用pivot_timestamps

      return $this->belongsToMany('users')->withPivot('timestamps');
      

      【讨论】:

      • 是否有可能从模型中的方法内按时间戳排序的数据透视表中获取最后一条记录?所以我将能够做到这一点:System::('users.lastRole, function($q){...})。它对我有用,但现在我有了“users.roles”,它为我提供了我可以通过关闭查询的所有角色,但我现在只需要拥有“users.lastRole”。
      猜你喜欢
      • 2020-01-25
      • 1970-01-01
      • 1970-01-01
      • 2016-10-15
      • 2015-02-24
      • 2014-01-15
      • 2021-01-09
      • 1970-01-01
      • 2017-10-17
      相关资源
      最近更新 更多