Creating a Nested Category API in Laravel 11

2 min read .

We’ll walk through the steps to create a nested category API in Laravel 11. We’ll build a system that allows categories to have parent-child relationships, enabling you to organize your data hierarchically. This is particularly useful for e-commerce platforms, content management systems, and other applications that require nested categories.

Step 1: Set Up Laravel Project

First, let’s create a new Laravel project:

composer create-project --prefer-dist laravel/laravel laravel-nested-categories
cd laravel-nested-categories
php artisan serve

Step 2: Create the Category Model and Migration

Next, we’ll generate a Category model along with a migration file:

php artisan make:model Category -m

Now, define the categories table structure in the migration file:

Schema::create('categories', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->unsignedBigInteger('parent_id')->nullable();
    $table->foreign('parent_id')->references('id')->on('categories')->onDelete('cascade');
    $table->timestamps();
});

Run the migration to create the table:

php artisan migrate

Step 3: Define Relationships in the Category Model

In the Category model, we’ll define the relationships to handle the parent-child hierarchy:

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'parent_id'];

    // Relationship to get the parent category
    public function parent()
    {
        return $this->belongsTo(Category::class, 'parent_id');
    }

    // Relationship to get the child categories
    public function children()
    {
        return $this->hasMany(Category::class, 'parent_id');
    }
}

Step 4: Create the CategoryController

Next, create a controller to handle API requests:

php artisan make:controller CategoryController

In the CategoryController, add methods to handle category listing and creation:

namespace App\Http\Controllers;

use App\Models\Category;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class CategoryController extends Controller
{
    public function index()
    {
        $categories = Category::with('children')
            ->whereNull('parent_id')
            ->get();

        return response()->json($categories);
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string',
            'children' => 'array',
            'children.*.name' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'code' => 422,
                'status' => 'error',
                'message' => 'Validation error',
                'errors' => $validator->errors(),
            ], 422);
        }

        $category = $this->createCategory($request->all());

        return response()->json(['category' => $category], 201);
    }

    private function createCategory($data, $parentId = null)
    {
        $category = Category::create([
            'name' => $data['name'],
            'parent_id' => $parentId,
        ]);

        if (!empty($data['children'])) {
            foreach ($data['children'] as $child) {
                $this->createCategory($child, $category->id);
            }
        }

        return $category->load('children');
    }
}

Step 5: Set Up API Routes

Enable API routing using the install:api:

php artisan install:api

Next, we’ll define the routes in routes/api.php:

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CategoryController;

Route::get('/categories', [CategoryController::class, 'index']);
Route::post('/categories', [CategoryController::class, 'store']);

Step 6: Testing the API

You can test the API using curl or any API testing tool like Postman.

Insert Nested Categories:

curl -X POST http://localhost:8000/api/categories \
-H "Content-Type: application/json" \
-d '{
    "name": "Electronics",
    "children": [
        {
            "name": "Mobile Phones",
            "children": [
                {
                    "name": "Smartphones"
                },
                {
                    "name": "Feature Phones"
                }
            ]
        },
        {
            "name": "Laptops"
        }
    ]
}'

Fetch Categories:

curl -X GET http://localhost:8000/api/categories

Conclusion

In this post, we’ve created a nested category API using Laravel 11. We set up the model, migration, controller, and routes to handle nested category creation and retrieval. This API can be extended further to include updating and deleting categories, as well as more complex querying based on your application’s needs.

Tags:
Laravel

See Also

chevron-up