How to make multi-level menu in laravel?

I'm building an ecommerce with a big menu where there are like 10 main categories, each of which contains many lower-level subcategories inside. For example, a main category "PC components" contains two sub-category of CPUs and Mainboards, then the CPU sub-category contains Intel and AMD, then Intel contains i3, i5, i7. I spent some hours researching and found that the problem might be solved by relational database with parent-child relations and nested foreach loops, somehow like below

//Controller
... compact('maincategories')->toArray (//each compacted maincategory array should contain all children and grandchildren, etc.);
//View
@foreach($maincategories as $maincategory)
   <h1>{{$maincategory['name']}}</h1>
      @foreach($maincategory['subcategories'] as $subcategory
         <h2>{{$subcategory['name']}}</h2>
                  @foreach($subcategory['subcategory_level_2s'] as $subcategory_level_2)
                   <h3>{{$subcategory_level_2['name']}}</h3>
@endforeach
@endforeach
@endforeach


However, I don't know how to set up relationship between them. I already know hasMany and belongsTo relations, but how to make them relate to each other is confusing. Any suggestion is appreciated. Thanks.

Hours spent. Can't set up the relations with sql table.

Upvotes: 0

Views: 134

Answers (1)

LayaCCC
LayaCCC

Reputation: 445

You need to set up foreign key in the migration.

Example as below.

First step: create migration by using artisan command

php artisan make:migration create_category_layer1_table
php artisan make:migration create_category_layer2_table

In the create_category_layer1_table file

public function up()
{
    Schema::create('category_layer1', function (Blueprint $table) {        
        $table->increments('id');
        $table->string('name');
    });
}

In the create_category_layer2_table file

public function up()
{
    Schema::create('category_layer2', function (Blueprint $table) {        
        $table->increments('id');
        $table->string('name');
        $table->integer('category_layer1_id')->unsigned();
        $table->foreign('category_layer1_id')->references('id')->on('category_layer1');
    });
}

Second step:Write Model.

php artisan make:model category_layer1
php artisan make:model category_layer2

The category_layer1 is the main categories, and the category_layer2 is the sub-category. Assume the relationship between category_layer1 and category_layer2 is One-To-Many. Hence, writing the relationship as below

In category_layer1 model

class category_layer1 extends Model
{
    public function category_layer2()
    {
        // According to the model path
        return $this->hasMany(\App\category_layer2::class);
    }
}

In category_layer2 model

class category_layer2 extends Model
{
    public function category_layer1()
    {
        // According to the model path
        return $this->belongsTo(\App\category_layer1::class);
    }
}

Final step: You can use the relationship in the controller to get data.

In controller

    $main_category = Category_layer1::with(['category_layer2'])
                                     ->whereNotNull('id')
                                     ->get()
    // Get the data
    foreach($main_category->category_layer2 as $category_layer2){
        \Log::info($category_layer2);
    }

You can create more categories you want.

If you create more categories, the code in the controller like below

// According to how many category level    
$main_category = Category_layer1::with(['category_layer2.category_layer3.category_layer4'])
               ->whereNotNull('id')
               ->get()

Upvotes: 1

Related Questions