In addition to what you're doing I also built my own [+][-] tree type thingy in JavaScript, with radio buttons and checkboxes to enable assigning a category to a parent, and assigning multiple products to multiple categories.
In fact it is an app I am working on now and I've spent about 3 months on it so far.
I'm afraid I am not going to write your app for you because I have my hands full doing my own :-) But maybe if I share my Category model it will give you a head start, particularly with the recursive relationships (in my app you can have an unlimited level of sub-catgories).
Migration:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('parent_id')->nullable();
$table->string('name', 255)->nullable();
$table->string('slug', 255)->nullable();
$table->unsignedBigInteger('priority')->default(0);
$table->timestamps();
$table->unique('parent_id', 'slug');
$table->foreign('parent_id')
->references('id')
->on('categories')
->onDelete('cascade');
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};
And then the model with relationships:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Category extends Model
{
/**
* Sub categories relationship.
*
* @return \Illuminate\Database\Eloquent\Relations\hasMany
*/
public function subCategories(): hasMany
{
return $this->hasMany(Category::class, 'parent_id');
}
/**
* All sub categories relationship.
*
* @return \Illuminate\Database\Eloquent\Relations\hasMany
*/
public function allSubCategories(): hasMany
{
return $this->hasMany(Category::class, 'parent_id')->orderBy('priority', 'asc')->with('allSubCategories');
}
/**
* Parent category relationship.
*
* @return \Illuminate\Database\Eloquent\Relations\belongsTo
*/
public function parent(): belongsTo
{
return $this->belongsTo(Category::class, 'parent_id');
}
/**
* Product relationship.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products(): BelongsToMany
{
return $this->belongsToMany(Product::class, 'product_category')
->orderByPivot('priority')
->orderBy('created_at');
}
}