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

FrazeColder's avatar

Laravel eloquent: Only retriev entries where relationship has entries (join)

Hi,

I have a products and a products_marks table. The products_marks table contains a user_id and a product_id and represents all products which are marked/saved by a user. So, this is more or less something like watch list.

My goal is now to perform a eloquent query which returns me only the products which are also present in the product_marks table for a certain user_id. For this example lets choose the user_id` 2.

This is my products.php model:

public function marks()
    {
        return $this->belongsToMany('App\Models\User', 'products_marks', 'product_id', 'user_id')->withTimestamps();
    }

This is how I archive what I want at the moment. I perform a eloquent query with a join. But how can I do this with a relationship?

$products = Product::join('products_marks', 'products_marks.product_id', '=', 'products.id')
            ->where('products_marks.user_id', 2)
            ->orderBy('created_at', 'desc')
            ->paginate(10);

Kind regards and thank you!

0 likes
11 replies
FrazeColder's avatar

Yes, this is working. Thank you. However, I do get all products instead of only the marked once.. is my relation wrong?

This is what I get as raw SQL: select * from products where exists (select * from users inner join products_marks on users.id = products_marks.user_id where products.id = products_marks.product_id and products_marks.user_id = 2) and page_status_id = 1 or page_status_id = 4 order by created_at desc

MichalOravec's avatar

Problem is this or page_status_id = 4

You don't show your full code here.

$products = Product::whereHas('marks', function ($query) {
    $query->where('products_marks.user_id', 2);
})->where(function ($query) {
    $query->where('page_status_id ', 1)->orWhere('page_status_id', 4);
})->orderBy('created_at', 'desc')->paginate(10);

or

$products = Product::whereHas('marks', function ($query) {
    $query->where('products_marks.user_id', 2);
})->whereIn('page_status_id', [1, 4])->orderBy('created_at', 'desc')->paginate(10);
FrazeColder's avatar

Yes, you are right!

This is my query at the moment:

$products = Product::whereHas('marks', function ($query) use ($user) {
            $query->where('products_marks.user_id', $user->id);
        })
            ->where('page_status_id', PageStatus::getIdByStatus('publish'))
            ->orWhere('page_status_id', PageStatus::getIdByStatus('pending'))
            ->orderBy('created_at', 'desc')
            ->paginate(10);

page_status_id represents whether a product is published (1) or pending (4). I want to get only published articles OR pending articles where the logged in user is also the author (products.user_id) of the product.

FrazeColder's avatar

I think I have it know. Is this correct?

$products = Product::whereHas('marks', function ($query) use ($user) {
            $query->where('products_marks.user_id', $user->id)
                ->where('page_status_id', PageStatus::getIdByStatus('publish'))
                ->orWhere('page_status_id', PageStatus::getIdByStatus('pending'))
                ->where('products.user_id', $user->id);
        })
            ->orderBy('created_at', 'desc')
            ->paginate(10);
FrazeColder's avatar

Yes, this is working. But I want to sort the complete relation either by products_marks.id or products_marks.created_at... how can I do this?

MichalOravec's avatar

If you want to order it by column in different table you have to use join as you have in OP.

FrazeColder's avatar

But this leads to the problem that my $appends attributes are not correct anymore...

MichalOravec's avatar
Level 75

$pageStatusIds = PageStatus::whereIn('status', [publish' , 'pending')->pluck('id')->toArray();

$products = Product::select('products.*')->join('products_marks', 'products_marks.product_id', '=', 'products.id')->whereHas('marks', function ($query) use ($user) {
    $query->where('products_marks.user_id', $user->id);
})->whereIn('page_status_id', $pageStatusIds)->orderBy('products_marks.created_at', 'desc')->paginate(10);

But in that case you don't need whereHas

FrazeColder's avatar

Thanks! You are a legend!

May any idea on my other thread about the comments and child comments?

Please or to participate in this conversation.