0
votes

I have two tables: products and categories. Every product have specific category.

The products table has category_id. The categories table has name and parent_id.

This is my example product: iPhone 12. In the admin section I have category Apple and subcategory iPhone and then I put the product (iPhone 12) inside the subcategory iPhone.

In the frontend section I can successfully display the category tree unordered list and when I click on the subcategory iPhone, the product iPhone 12 displays fine but when I click on the category Apple, the product doesn't show. How can I display the data from the parent, so when I click on Apple category or iPhone subcategory to display the product in both cases?

Here's my code:

Model category

public function products()
{
    return $this->hasMany('App\Models\Product');
}

public function children() {
  return $this->hasMany('App\Models\Category', 'parent_id');
}

Category model

public function products()
{
    return $this->hasMany('App\Models\Product');
}

ProductController

public function productCategory(Category $category) {
  $categories = Category::with('children')->whereNull('parent_id')->where('status',1)->get();
  $products = $category->products;

  return view('products', compact('products', 'categories'));

}

Route

Route::get('/category/{category:slug}', 'App\Http\Controllers\ProductController@productCategory')->name('product.category');

Products view:

  <div class="content products">
    <div class="container">
      <div class="row">
        <div class="col-md-3">
          <div class="categories">
            <ul>
              @foreach($categories as $category)
                <li>
                  <a href="{{ route('product.category', $category->slug) }}">{{ $category->name }}</a>
                  @if($category->children)
                  <ul>
                    @foreach($category->children as $child)
                      <li>
                        <a href="{{ route('product.category', $child->slug) }}">{{ $child->name }}</a>
                      </li>
                    @endforeach
                  </ul>
                  @endif
                </li>
              @endforeach
            </ul>
          </div>
        </div>
        <div class="col-md-9">
          <div class="row">
            @foreach($products as $product)
              <div class="col-sm-4">
                <div class="image">
                  <a href="{{ route('product', $product->slug) }}"><img class="img-fluid" src="{{ Storage::url($product->image) }}" /></a>
                </div>
                <div class="title">
                  <h3>{{ $product->title }}</h3>
                </div>
              </div>
            @endforeach
          </div>
        </div>
      </div>
    </div>
  </div>
2
Please show your category model.Shahrukh
Are you able to fetch $slug name in productCategory Function?Yasin Patel
@Shahrukh I've updated my post.user2519032
@YasinPatel Yes, with dd($category); I'm getting all data including the slug.user2519032
@user2519032, currently you are getting all products? bcs you are not using $category anywhereYasin Patel

2 Answers

0
votes

I think you could use hasManyThrough function provided by laravel

In the category model add these functions

//retrunt only the subcategories of the category 
public function subcategories()
{
   return $this->hasMany(Category::class,'parent_id');
}
//return the products directly by the parent category
public function categotyProducts()
{
   return $this->hasManyThrough(
        Product::class,
        category::class,
        'parent_id', 
        'category_id', 
    );
}

for more information see the docs

Hope that works for you!

0
votes

In your Product model define category relationship as below.

public function category()
{
    return $this->belongsTo('App\Models\Category','category_id');
}

In your controller function define slug variable and use below query to get Products

$slug = ($category->slug)??'';

Query for products:

$products = Product::where(function($query) use ($slug){
                            $query->whereHas('category',function($q) use ($slug){
                              $q->where('name', 'like', '%' . $slug . '%');
                            })
                            ->orWhereHas('category.children',function($q) use ($slug){
                              $q->where('name', 'like', '%' . $slug . '%');
                            });
                          })->get();