Laravel 12 REST API for Product Management with Full CRUD Support
Laravel is a powerful PHP framework that simplifies modern web development. In this tutorial, we’ll guide you through building a RESTful Product Management API in Laravel 12, fully updated for Laravel’s new minimalist structure.
We’ll use:
- Laravel 12
- MySQL database
php artisan install:api- REST API principles
- Postman for testing
✨ Features
- Retrieve Products: Fetch all or a specific product.
- Create Products: Add new products.
- Update Products: Modify existing product data.
- Delete Products: Remove product records.
🚀 Step 1: Create Laravel 12 Project
composer create-project laravel/laravel laravel12-rest-api
cd laravel12-rest-api
⚙️ Step 2: Set Up API Structure (Laravel 12+)
Since Laravel 12 uses a minimal skeleton:
php artisan install:api
This command generates:
routes/api.php- Middleware registration in
bootstrap/app.php
📁 bootstrap/app.php
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(
basePath: dirname(__DIR__)
)
->withRouting(
web: __DIR__ . '/../routes/web.php',
api: __DIR__ . '/../routes/api.php',
commands: __DIR__ . '/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
// Register middleware here
})
->withExceptions(function (Exceptions $exceptions) {
// Handle exceptions here
})
->create();
💡 Step 4: Create the Product Model and Migration
php artisan make:model Product -m
Update the generated migration file in database/migrations/:
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description');
$table->decimal('price', 10, 2);
$table->timestamps();
});
}
Then run:
php artisan migrate
🖊️ Step 5: Create the ProductController
php artisan make:controller ProductController --resource
Update app/Http/Controllers/ProductController.php:
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function index()
{
return response()->json(Product::all(), 200);
}
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'description' => 'required|string',
'price' => 'required|numeric|min:0',
]);
$product = Product::create($validated);
return response()->json($product, 201);
}
public function show($id)
{
$product = Product::find($id);
if (!$product) {
return response()->json(['message' => 'Product not found'], 404);
}
return response()->json($product);
}
public function update(Request $request, $id)
{
$product = Product::find($id);
if (!$product) {
return response()->json(['message' => 'Product not found'], 404);
}
$validated = $request->validate([
'name' => 'sometimes|required|string|max:255',
'description' => 'sometimes|required|string',
'price' => 'sometimes|required|numeric|min:0',
]);
$product->update($validated);
return response()->json($product);
}
public function destroy($id)
{
$product = Product::find($id);
if (!$product) {
return response()->json(['message' => 'Product not found'], 404);
}
$product->delete();
return response()->json(['message' => 'Product deleted successfully']);
}
}
🚪 Step 6: Define API Routes
Open routes/api.php and add:
use App\Http\Controllers\ProductController;
Route::apiResource('products', ProductController::class);
✍️ Step 7: Allow Mass Assignment in the Product Model
Update app/Models/Product.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Product extends Model
{
use HasFactory;
protected $fillable = ['name', 'description', 'price'];
}
🚪 Step 8: Test API Endpoints
Use Postman or curl to test:
1. Get All Products
- Method:
GET - URL:
http://localhost:8000/api/products
2. Create Product
- Method:
POST - URL:
http://localhost:8000/api/products - Body:
{
"name": "Laptop",
"description": "A high-performance laptop",
"price": 1500.00
}
3. Get a Specific Product
- Method:
GET - URL:
http://localhost:8000/api/products/{id}
4. Update a Product
- Method:
PUT - URL:
http://localhost:8000/api/products/{id} - Body:
{
"name": "Gaming Laptop",
"price": 1800.00
}
5. Delete a Product
- Method:
DELETE - URL:
http://localhost:8000/api/products/{id}
🔐 Laravel 12 REST API with Sanctum Authentication (Extended CRUD)
In this tutorial, we’ll extend our Laravel 12 Product CRUD API to use Laravel Sanctum for secure token-based authentication. This lets you protect routes and only allow authenticated users to manage products.
📦 Requirements
- Laravel 12
- MySQL database
- Laravel Sanctum package
- Postman (for API testing)
🛠️ Step 1: Install Sanctum
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
⚙️ Step 2: Register Sanctum Middleware
Open bootstrap/app.php and add inside withMiddleware():
$middleware->alias([
'auth:sanctum' => \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
]);
👤 Step 3: Update User Model
In app/Models/User.php:
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
// ...
}
🧑💻 Step 4: Create AuthController
php artisan make:controller AuthController
Then update app/Http/Controllers/AuthController.php:
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
class AuthController extends Controller
{
public function register(Request $request)
{
$validated = $request->validate([
'name' => 'required',
'email' => 'required|email|unique:users',
'password' => 'required|confirmed|min:6',
]);
$user = User::create([
'name' => $validated['name'],
'email' => $validated['email'],
'password' => Hash::make($validated['password']),
]);
$token = $user->createToken('api-token')->plainTextToken;
return response()->json(['user' => $user, 'token' => $token], 201);
}
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required'
]);
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
return response()->json(['message' => 'Invalid credentials'], 401);
}
$token = $user->createToken('api-token')->plainTextToken;
return response()->json(['user' => $user, 'token' => $token]);
}
public function logout(Request $request)
{
$request->user()->tokens()->delete();
return response()->json(['message' => 'Logged out successfully']);
}
}
🛣️ Step 5: Register Auth & Protected Routes
In routes/api.php:
use App\Http\Controllers\AuthController;
use App\Http\Controllers\ProductController;
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
Route::post('/logout', [AuthController::class, 'logout']);
Route::apiResource('products', ProductController::class);
});
🧪 Step 6: Test with Postman
1️⃣ Register
- Method: POST
- URL:
http://localhost:8000/api/register
{
"name": "Umar",
"email": "umar@example.com",
"password": "secret123",
"password_confirmation": "secret123"
}
2️⃣ Login
- Method: POST
- URL:
http://localhost:8000/api/login
{
"email": "umar@example.com",
"password": "secret123"
}
3️⃣ Use Token in Header
In all protected requests (CRUD):
Authorization: Bearer YOUR_TOKEN_HERE
4️⃣ Access Product Routes
GET /api/productsPOST /api/productsPUT /api/products/{id}DELETE /api/products/{id}
✅ Summary
- ✅ Laravel 12 Product CRUD API implemented
- ✅ Sanctum authentication integrated
- ✅ Protected routes using
auth:sanctum - ✅ Token-based access via Postman
Now your Laravel 12 REST API is secure and production-ready with authentication!
