Building a Simple E-Commerce Website with Laravel – Step 2: Database & Models Setup
In our previous post, we set up a Laravel project and created a basic homepage. Now, it’s time to build the backbone of our e-commerce application – the database structure and models. This step is crucial because it defines how products, categories, and orders will be stored, related, and accessed.
By the end of this post, you’ll have a well-structured database and Laravel models ready for CRUD operations.
Step 1: Planning the Database Structure
Before writing any migrations, it’s important to plan the database tables and relationships. For a simple e-commerce site, we’ll need the following tables:
- Categories – To group products into sections (e.g., Electronics, Clothing).
id(primary key)name(string)description(text, optional)created_at,updated_at(timestamps)
- Products – The items we sell.
id(primary key)category_id(foreign key)name(string)description(text)price(decimal)stock(integer)image(string, optional)created_at,updated_at
- Orders – To store customer purchases.
id(primary key)user_id(foreign key, optional for guest checkout)total_price(decimal)status(enum: pending, completed, canceled)created_at,updated_at
- Order_Items – To track products in each order.
id(primary key)order_id(foreign key)product_id(foreign key)quantity(integer)price(decimal)
Tip: Taking time to plan your database reduces future headaches. Think about how tables relate, what data is required, and what can be optional.
Step 2: Creating Migrations
Laravel migrations are PHP files that define your database schema. Let’s create tables step by step.
- Categories Table
php artisan make:migration create_categories_table --create=categories
In database/migrations/xxxx_create_categories_table.php:
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description')->nullable();
$table->timestamps();
});
}
- Products Table
php artisan make:migration create_products_table --create=products
public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->foreignId('category_id')->constrained()->onDelete('cascade');
$table->string('name');
$table->text('description');
$table->decimal('price', 10, 2);
$table->integer('stock')->default(0);
$table->string('image')->nullable();
$table->timestamps();
});
}
- Orders Table
php artisan make:migration create_orders_table --create=orders
public function up(): void
{
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->nullable()->constrained()->onDelete('set null');
$table->decimal('total_price', 10, 2);
$table->enum('status', ['pending', 'completed', 'canceled'])->default('pending');
$table->timestamps();
});
}
- Order Items Table
php artisan make:migration create_order_items_table --create=order_items
public function up(): void
{
Schema::create('order_items', function (Blueprint $table) {
$table->id();
$table->foreignId('order_id')->constrained()->onDelete('cascade');
$table->foreignId('product_id')->constrained()->onDelete('cascade');
$table->integer('quantity');
$table->decimal('price', 10, 2);
$table->timestamps();
});
}
- Run All Migrations
php artisan migrate
This will create all tables in your database.
Step 3: Creating Eloquent Models
Models in Laravel represent database tables and allow easy interaction with data. Let’s create models for our tables.
- Category Model
php artisan make:model Category
In app/Models/Category.php:
class Category extends Model
{
protected $fillable = ['name', 'description'];
public function products()
{
return $this->hasMany(Product::class);
}
}
- Product Model
php artisan make:model Product
class Product extends Model
{
protected $fillable = ['category_id', 'name', 'description', 'price', 'stock', 'image'];
public function category()
{
return $this->belongsTo(Category::class);
}
public function orderItems()
{
return $this->hasMany(OrderItem::class);
}
}
- Order Model
php artisan make:model Order
class Order extends Model
{
protected $fillable = ['user_id', 'total_price', 'status'];
public function orderItems()
{
return $this->hasMany(OrderItem::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
- OrderItem Model
php artisan make:model OrderItem
class OrderItem extends Model
{
protected $fillable = ['order_id', 'product_id', 'quantity', 'price'];
public function order()
{
return $this->belongsTo(Order::class);
}
public function product()
{
return $this->belongsTo(Product::class);
}
}
Step 4: Understanding Relationships
Here’s how the tables relate:
- A Category has many Products.
- A Product belongs to one Category and can appear in many OrderItems.
- An Order has many OrderItems.
- An OrderItem belongs to one Order and one Product.
Tip: Naming conventions matter. Using singular model names and plural table names keeps Laravel’s conventions consistent.
Step 5: Testing the Models with Tinker
Laravel Tinker allows testing database operations quickly.
php artisan tinker
Example:
$category = Category::create(['name' => 'Electronics']);
$product = Product::create([
'name' => 'Smartphone',
'description' => 'Latest model smartphone',
'price' => 699,
'stock' => 50,
'category_id' => $category->id
]);
$product->category; // Returns the Electronics category
This confirms that our relationships and models work correctly.
Step 6: Key Takeaways
- Planning your database structure first saves time and ensures data consistency.
- Laravel migrations make schema changes manageable.
- Eloquent models allow you to interact with the database using clean, readable code.
- Proper relationships simplify retrieving related data, like getting all products in a category or items in an order.
Personal Note
When I first learned Laravel, setting up the database and models was the most intimidating part. But once I saw how Eloquent handles relationships effortlessly, I realized that a strong foundation makes building features like carts, checkout, and user accounts much easier.
Next Steps
In the next post, we’ll implement CRUD operations for products and categories, and display them dynamically on the homepage. This will turn our static homepage into a functional e-commerce platform.