Laravel:具有多对多关系的历史排名系统

Posted

技术标签:

【中文标题】Laravel:具有多对多关系的历史排名系统【英文标题】:Laravel: Historical ranking system with ManyToMany relationship 【发布时间】:2016-06-13 21:30:52 【问题描述】:

我想显示一个按排名列出用户的页面。一个排名可以有多个用户(例如,2 个用户可以排在第二位),一个用户也可以有多个排名,因为我想保留用户和排名的历史记录。

这里是User.php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable

    // ...

    public function Ranks() 
        return $this->belongsToMany('App\Rank');
    

还有Rank.php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Rank extends Model

    public $timestamps = false;

    public function Users() 
        return $this->belongsToMany('App\User')->withPivot('created_at');
    

我的数据库中还有一个rank_user 表,其中包含idrank_iduser_idcreated_at 字段。

这是我在数据库中记录的方式:

$user->ranks()->attach($rank_id, ['created_at' => Carbon::now()->addMinutes(105)]);

为了按排名列出用户,我的意思是在当前(最近)排名,这就是我所拥有的:

$ranks = Rank::with('users')->get();

例如,对于第一名,它给我所有从一开始就排在第一位的用户,而不是给我所有当前排在第一位的用户。

我不知道如何将查询限制为最近的日期。

【问题讨论】:

假设用户获得了排名 1,但之后一年没有玩游戏。他们是否还应该与最近获得 1 级的其他 1 级的人一起返回? hmm,你需要得到所有等级,使用 created_at 的每个用户的最后一条记录,我到现在都找不到正确的代码,这真是一个有趣的问题 试试这个$rank = App\Rank::with(['users' => function ($query) $query->latest(); ])->get(); @Samsquanch:即使用户一年不玩游戏,也会在rank_user 表中插入一条新记录,其中包含今天的日期。因此,如果有人比第一个一年没有上场的球员得分多,他就会击败他。 @AchrafKhouadja:您的代码不起作用,因为它列出了所有已经获得第一名、第二名等的用户...在下面查看我的答案:) 【参考方案1】:

我问了我的一位朋友,这是我们找到的解决方案:

我首先必须将最近的日期包含在 rank_user 数据透视表中。

$date = DB::table('rank_user')->select('created_at')
                              ->orderBy('created_at', 'desc')
                              ->first();

然后,我可以使用withPivot() 指定我只想要我们之前找到的最近日期的结果:

$ranks = Rank::with(['users' => function($query) use ($date) 
    $query->wherePivot('created_at', $date->created_at);
])->get();

瞧!这样,我只能获取每个排名中最近的用户。

【讨论】:

以上是关于Laravel:具有多对多关系的历史排名系统的主要内容,如果未能解决你的问题,请参考以下文章

laravel中具有多对多关系的高级搜索

laravel 使用具有多对多关系数据透视表的策略

Laravel:具有 whereHas 和多对多关系的全局范围

Laravel 上的多对多问题关系

Laravel 多对多关系计数

Laravel - 播种多对多关系