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
相关产品推荐
相关产品推荐

