0
votes

I have the following 3 models on my app:

  • Product
  • Subcategory
  • Category

A product belongs to a subcategory that belongs to a category. Each product belongs to just one subcategory, a subcategory can have N products but belongs to just one category and a category can also have multiple subcategories.

At this point I'm able to go from a product to his subcategory and jump to the main category, here a example from tinker console:

>>> $product = App\Models\Product::Find(1);
=> App\Models\Product {#4156
     id: "1",
     name: "Jersey",
     description: "Black Jersey",
     type_id: "1",
     brand_id: "1",
     subcategory_id: "1",
     created_at: "2021-03-03 00:46:26",
     updated_at: "2021-03-03 00:46:26",
   }
>>> $product->subcategory;
=> App\Models\Subcategory {#3684
     id: "1",
     category_id: "1",
     name: "Top",
     created_at: "2021-03-03 00:44:31",
     updated_at: "2021-03-03 00:44:31",
   }
>>> $product->subcategory->category;
=> App\Models\Category {#4246
     id: "1",
     category: "Clothing",
     created_at: "2021-03-03 00:42:14",
     updated_at: "2021-03-03 00:42:14",
   }
>>> 

But when I try to do the same from category to subcategories and getting al the products with the same subcategory I get this error:

>>> $category = App\Models\Category::Find(1);
=> App\Models\Category {#4299
     id: "1",
     category: "Clothing",
     created_at: "2021-03-03 00:42:14",
     updated_at: "2021-03-03 00:42:14",
   }
>>> $category->subcategory;
=> Illuminate\Database\Eloquent\Collection {#4305
     all: [
       App\Models\Subcategory {#4300
         id: "1",
         category_id: "1",
         name: "Top",
         created_at: "2021-03-03 00:44:31",
         updated_at: "2021-03-03 00:44:31",
       },
     ],
   }
>>> $category->subcategory->product;
Exception with message 'Property [product] does not exist on this collection instance.'
>>> 

Here are the models I' working with:

Product:

public function subcategory(){
        return $this->belongsTo(Subcategory::class);
    }

Category:

public function subcategory(){
        return $this->hasMany(Subcategory::class);
    }

Subcategory:

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

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

I would like to be able to get all the products belonging to the same category (meaning that belong to different subcategories but under the same category) or all the same subcategory.

3

3 Answers

1
votes

You need to use the hasManyThrough relation.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Category extends Model {

    /**
     * Get all of the products for the project.
     */

    public function products()
    {
        return $this->hasManyThrough(Product::class, Subcategory::class);
    }
}

You can use this relation as

$category = App\Models\Category::Find(1);

$products = $category->products
1
votes

you can use the hasManyThrough relationship in this case to get all products of a category. add this on your category model.

public function products()
{
    return $this->hasManyThrough(Product::class, Subcategory::class);
}

in your current approach, you are getting a collection form $category->subcategory and you have to loop through the collection to get the products of each sub category. so the best option for you is to use the hasManyThrough relation and you can simply call $category->products that will return you all the products of the category.

1
votes

If you get current product with Eloquent:

$product= Product::find(5);

You can use this:

$result = Product::whereIn('subcategory_id', function($query){
    $query->select('subcategory_id')
    ->from(with(new Category)->getTable())
    ->where('id', $product->subcategory->category->id);
})->where('subcategory_id','!=',$product->subcategory->id)->get();