You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 5.6:判断用户与测评多对多关系及通过状态问题

解决Laravel 5.6中User与Assessment多对多关系的测评状态判断问题

嘿,我来帮你搞定这个多对多关系的测评状态判断问题!首先咱们得先把模型关联的坑填上,然后再讲怎么正确判断用户的测评状态(未参加、未通过、已通过)。

第一步:修正User模型的关联代码

你说User模型的关联有问题,大概率是没正确指定中间表,也没带上判断是否通过的中间表字段。咱们先把关联写对:

在User.php里:

public function assessments()
{
    // 关联Assessment模型,中间表是attempts,同时带上中间表的is_passed字段(用来判断是否通过)
    return $this->belongsToMany(Assessment::class, 'attempts')
                ->withPivot('is_passed');
}

这里的is_passed是我假设的中间表字段,你可以根据实际表结构调整(比如叫passed之类的),核心是要把中间表中存储通过状态的字段通过withPivot带出来,不然没法判断是否通过。

对应的,Assessment.php里的关联也可以写上(可选,但规范):

public function users()
{
    return $this->belongsToMany(User::class, 'attempts')
                ->withPivot('is_passed');
}

第二步:遍历所有测评并判断用户状态

现在关联没问题了,咱们就可以遍历所有Assessment,逐个判断指定用户的状态:

// 获取指定用户
$targetUser = User::find(你的用户ID);
// 获取所有测评
$allAssessments = Assessment::all();

foreach ($allAssessments as $assessment) {
    // 先检查用户是否参加过这个测评
    $userAttempt = $targetUser->assessments()->where('assessment_id', $assessment->id)->first();
    
    if (!$userAttempt) {
        // 情况1:用户未参加该测评
        echo "测评「{$assessment->title}」:未参加";
    } elseif (!$userAttempt->pivot->is_passed) {
        // 情况2:用户参加了但未通过
        echo "测评「{$assessment->title}」:未通过";
    } else {
        // 情况3:用户已通过
        echo "测评「{$assessment->title}」:已通过";
    }
}

为什么你之前用contains没成功?

contains方法默认只是检查用户和该测评是否存在关联记录(也就是有没有参加),但没法直接判断是否通过。如果要结合contains来用,得这么做:

foreach ($allAssessments as $assessment) {
    // 先判断是否参加过
    $hasAttempted = $targetUser->assessments->contains($assessment->id);
    
    if (!$hasAttempted) {
        echo "测评「{$assessment->title}」:未参加";
    } else {
        // 找到该测评的关联记录,检查是否通过
        $attempt = $targetUser->assessments->where('id', $assessment->id)->first();
        if ($attempt->pivot->is_passed) {
            echo "测评「{$assessment->title}」:已通过";
        } else {
            echo "测评「{$assessment->title}」:未通过";
        }
    }
}

不过这种方式会多一次集合查询,不如直接用关联查询的效率高,所以更推荐前面第一种写法。

补充:中间表结构参考

你的attempts中间表至少需要这些字段:

Schema::create('attempts', function (Blueprint $table) {
    $table->unsignedInteger('user_id');
    $table->unsignedInteger('assessment_id');
    $table->boolean('is_passed')->default(false); // 存储通过状态
    $table->timestamps();

    // 设置外键约束(可选但推荐)
    $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    $table->foreign('assessment_id')->references('id')->on('assessments')->onDelete('cascade');

    // 设置联合主键
    $table->primary(['user_id', 'assessment_id']);
});

内容的提问来源于stack exchange,提问作者Moose

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:07:47