Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

bufferoverflow's avatar

Possible bug with wherePivot() ?

I have noticed a possible bug. The following method inside Course::class returns students who meet any of the wherePivot() conditions, even if not related to the course by the belongsToMany relationship.

    // should return $course->students that have an active subscription
    public function activeStudents()
    {
        return $this->belongsToMany(Student::class)
        ->using(CourseStudent::class)
        ->withPivot('expires_at', 'balance_id')
        ->wherePivot('expires_at', '>=', Carbon::now())
        ->orWherePivotNull('expires_at')
        ->withTimestamps();
    }

If I remove the wherePivot conditions I correctly get all students from the $course, but adding these conditions returns students from other courses as well. There's no advances/custom wherePivot so I'm not sure how this could be solved.

0 likes
4 replies
MichalOravec's avatar

You should always group orWhere calls in order to avoid unexpected behavior when global scopes are applied.

->where(function ($query) {
    $query->wherePivot('expires_at', '>=', Carbon::now())
        ->orWherePivotNull('expires_at');
})
1 like
bufferoverflow's avatar

@MichalOravec Thanks, but I think subqueries do not work for wherePivot conditions.

public function activeStudents()
{
        return $this->belongsToMany(Student::class)
            ->where(function ($query) {
                $query->wherePivot('expires_at', '>=', Carbon::now())
                    ->orWherePivotNull('expires_at');
            });
}

The above code returns BadMethodCallException with message 'Call to undefined method Illuminate\Database\Eloquent\Builder::orWherePivotNull()'

MichalOravec's avatar
Level 75

@bufferoverflow In that case use classic where

->where(function ($query) {
    $query->where('pivot_table_name.expires_at', '>=', Carbon::now())
        ->orWhereNull('pivot_table_name.expires_at');
})
1 like

Please or to participate in this conversation.