0

使用 Laravel 7.0

我有 3 个模型(MeetingMeetingVersionUser)和 4 个表(Meetingmeeting_versionsusersmeeting_versions_users)。

一个会议有许多MeetingVersion模型,其中每个版本都many-to-manyUser有关系。每个MeetingVersion都有一个meeting_id指向其父Meeting的外键。用户通过meeting_versions_users数据透视表关联到一个 MeetingVersion。

现在,我想选择最新版本与给定用户 ID 相关联的所有会议。

会议班

public function versions()
{
    return $this->hasMany(MeetingVersion::class, 'meeting_id');
}

会议版本类

public function users()
{
    return $this->belongsToMany(User::class, 'meeting_versions_users', 'version_id', 'user_id');
}

会议

+----+
| id |
+----+
| 10 |
| 11 |
+----+

会议版本

+----+------------+---------+
| id | meeting_id | version |
+----+------------+---------+
| 31 |         10 |       1 |
| 32 |         10 |       2 |
| 33 |         10 |       3 | <- latest version (33) for meeting id 10
| 34 |         11 |       1 |
| 35 |         11 |       2 | <- latest version (35) for meeting id 11
+----+------------+---------+

会议版本用户

+------------+---------+
| version_id | user_id |
+------------+---------+
|         31 |     101 |
|         32 |     101 |
|         33 |     102 | <- user associated with latest version for meeting id 10
|         34 |     101 |
|         35 |     101 | <- user associated with latest version for meeting id 11
+------------+---------+

用户

+-----+
| id  |
+-----+
| 101 |
| 102 |
+-----+

这是我正在尝试的查询。我应该只返回会议 11,但此查询返回用户 101 的两个会议。

// Some user id.
$userId = 101;


// Query to get all meetings where user is associated with latest version of meeting.

$meeting = Meeting::query()->where(function (Builder $query) use ($userId) {

        $query->whereHas('versions', function (Builder $query) use ($userId) {

            /*
             * I want to get just the "latest" version model here, so that further queries are constrained to that model only.
             * As it is now, the below whereHas query is applied to all child models.
             * Using $query->latest('version')->limit(1) doesn't work here as expected.
             *
             * So, I need to a way to limit the following whereHas query to the latest version.
             * This constraint should be applied to just the "latest" model relation, instead of all models.
            */

            $query->whereHas('users', function (Builder $query) use ($userId) {
                $query->where('id', $userId);
            });

        });
    })->get();

对此非常感谢的任何帮助。

4

2 回答 2

0

在你的问题中你说:

  • 使用 $query->latest('version')->limit(1) 在此处无法按预期工作。

因为 laravel 得到了整个查询的最后一个 MeetingVersion !不是每次会议

使用eloquent-eager-limit来解决这个问题

安装它:

composer require staudenmeir/eloquent-eager-limit:"^1.0"

然后在会议模型中:

class Meeting extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
.....
public function lastMeetingVersion()
{
return $this->hasMany(MeetingVersion::class, 'meeting_id')
->orderBy('id','desc')->limit(1);
}
    }

在 MeetingVersion 中:

class MeetingVersion extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
......
}

现在限制将按您的预期工作....

$meeting = Meeting::query()->with(['lastMeetingVersion' => function ($query)
        use ($userId) {
            $query->whereHas('users', function ($q) use ($userId) {
                $q->where('id', $userId);
            });
        }]);

更多细节在:eloquent-eager-limit

于 2020-06-12T20:28:31.073 回答
0

您可以使用 subselect 来获取每个会议的最大版本 ID。

$meetings = Meeting::query()
    ->whereHas('versions', function (Builder $query) use ($userId) {
        $query->addSelect([
            'max_meeting_version_id' => MeetingVersion::select('id')->whereColumn('meeting_id', 'meeting.id')
                ->orderBy('version', 'desc')->limit(1)
        ])->whereHas('users', function (Builder $query2) use ($userId) {
            $query2->where('users.id', $userId);
        })
            ->havingRaw('max_meeting_version_id = meeting_versions.id');
    })
    ->get();
于 2020-06-12T21:49:10.637 回答