peterdickins's avatar

With() WhereHas()

Hi,

I am building a shopping cart, and I have the following models Category, Product and Sku.

A Category is a many to many relationship to a product and a product has many Skus.

class Category extends Model
{    
    public function products(): BelongsToMany
    {
        return $this->belongsToMany(Product::class);
    }

    public function skus()
    {
        return $this->hasManyThrough(
            Sku::class,
            CategoryProduct::class,
            'category_id',
            'product_id',
            'id',
            'product_id'
        );
    } 
}

class Product extends Model
{
    public function skus(): HasMany
    {
        return $this->hasMany(Sku::class);
    }

    public function categories(): BelongsToMany
    {
        return $this->belongsToMany(Category::class);
    }
}

class Sku extends Model
{
    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }
}

In the category index route I need to return all categories, but only those which have products and a sku. I have tried the following:

public function all(): Collection
{
    return Category::with('products')
        ->whereHas('skus')
        ->get();
}

But this returns categories with products, regardless of whether the product has a sku. Can anyone advise who I can fix this please?

0 likes
5 replies
tisuchi's avatar

@peterdickins Try this:

public function all(): Collection
{
    return Category::with('products')
        ->whereHas('products', function($query) {
            $query->whereHas('skus');
        })
        ->get();
}
peterdickins's avatar

Thank you @tisuchi I tried this but the query still returns products that don't have skus attached to them

krisi_gjika's avatar
Level 14

@peterdickins something like:

public function all(): Collection
{
    return Category::with(['products' => fn ($query) => $query->whereHas('skus')])
        ->get();
}

or create a new relation skuProducts on your category model and apply the where condition there

peterdickins's avatar

@krisi_gjika thank you, this is returning the products that only have skus attached, however it is also returning categories that have no skus, how can I fix this?

Please or to participate in this conversation.