0
votes

As mentioned in the title, the problem is how to list the subcategories under the parent category based on the product. I have no problem listing out the parent category and all its subcategories as I have shown in the sample code at the end of this post. But I need to list out the subcategories based on the product.

This is the sample structure of my categories:

Electronic
-Computer
-Phone
-Gadget

Grocery
-Food
-Drinks

This is my products table migration:

   Schema::create('products', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->decimal('price')->nullable();
        $table->timestamps();
    });

This is my categories table migration

   Schema::create('categories', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('parent_id')->nullable();
        $table->string('name')->nullable();
        $table->string('description')->nullable();
        $table->timestamps();
    });

and this one is the category_product which acts as for many to many table between category and product:

    Schema::create('category_product', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('product_id')->unsigned()->index();
        $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
        $table->integer('category_id')->unsigned()->index();
        $table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
        $table->timestamps();
    });

I have setup all the relationship. Here are my models:

This is my category model:

class Category extends Model
{
    protected $table = 'categories';

    protected $fillable = [
        'name',
    ];
    public function products()
    {
        return $this->belongsToMany('App\Product');
    }

    public function parent()
    {
        return $this->belongsTo('App\Category', 'parent_id');
    }

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

}

This is my product model:

class Product extends Model
{
   public function categories()
   {
     return $this->belongsToMany('App\Category');
   }
}

This is my ProductController.php, I'm able to display all parents category with its subcategories using this code:

public function show($id)
 {   
      $product = Product::findOrFail($id); 
      $categories = Category::with('children')->get();
      return view('products.show', compact('product','categories'));

 }

So my product.shows.blade looks like this:

@foreach($categories as $item)
    @if($item->children->count() > 0 )
        <li>
            {{ $item->name }}
            <ul>
                @foreach($item->children as $submenu)
                    <li>{{ $submenu->name }}</li>
                @endforeach
            </ul>
        </li>
    @endif

@endforeach

//OUTPUT:

Electronic  
 Computer
 Phone
 Gadget

Grocery
 Food
 Drinks

But let say that this particular product (called Product 1) has the parent category of Electronic and the subcategory is Computer and Phone which I already attached them in the database. This is the overview of the data from the database:

products table

categories table

category_product table

How do I display the category of Product 1 with its parent and subcategories? I want the output to be like

Product 1 

Category:
 Electronic
  Computer
  Phone

Update:

So, another thing that I have done was adding the $product->categories but the code will only list out a parent category that the Product1 has with all its subcategories. It doesn't filter the subcategories specific to the Product1

   @foreach($product->categories as $item)
        @if($item->children->count() > 0 )
            <li>
                {{ $item->name }}
                <ul>
                    @foreach($item->children as $submenu)
                        <li>{{ $submenu->name }}</li>
                    @endforeach
                </ul>
            </li>
        @endif
    @endforeach

So, instead of the output like this (which i want):

Category:
 Electronic
  Computer
  Phone

it will list out like this (which is not i want):

Category:
 Electronic
  Computer
  Phone
  Gadget
1

1 Answers

1
votes

Roughly like so:

Controller

$product = Product::with('categories.parent')->findOrFail($id);
$categories = $product->categories->groupBy('parent_id');

@foreach($categories as $parent_id => $children)

    @if($children->first()->parent}}

    Parent {{$children->first()->parent->name}}
    @foreach($children as $child)
         //print child
    @endforeach

    @endif

@endforeach