peterdickins's avatar

Eloquent relationships - Has Many

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);
    }
}

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);
    }
}

I need to add a relationship from Category to Sku, how can I do this? I have tried has many through but it doesn't work:

public function skus()
{
    return $this->hasManyThrough(Sku::class, Product::class);
}
0 likes
4 replies
Snapey's avatar

You cannot natively do hasManyThrough on a many to many relationship

You want to know all the skus in a category or the categories a single sku might belong to?

1 like
Snapey's avatar

So I would probably do two queries

  • get the $ids of all products in the category as an array

  • get all the skus that are ->whereIn('product_id', $ids)

1 like
newbie360's avatar
Level 24

@peterdickins

Create a pivot model CategoryProduct.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\Pivot;

class CategoryProduct extends Pivot
{
    public function category()
    {
        return $this->belongsTo(Category::class);
    }

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

Category model add new relationship

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

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

Usage

Category::with('productSkus')->get();

Category::withCount('productSkus')->get();

Category::with('productSkus')->find(123);
3 likes

Please or to participate in this conversation.