api-integration web-development notifications user-authentication animations e-commerce-platform custom-e-commerce order-processing shopping-cart vuex
Tutorial: Building a Custom E-commerce Platform with Laravel and Vue.js
Introduction
Building a custom e-commerce platform can be a rewarding endeavor, offering flexibility, scalability, and control over the user experience. In this tutorial, we will guide you through the process of creating a custom e-commerce platform using Laravel for the backend and Vue.js for the frontend. By the end of this tutorial, you'll have a solid foundation for a fully functional e-commerce platform that you can expand and customize according to your needs.
Prerequisites
Before we begin, make sure you have the following:
- Basic Knowledge of Laravel: Understanding Laravel’s MVC structure, routing, and Eloquent ORM is essential.
- Basic Knowledge of Vue.js: Familiarity with Vue.js components, directives, and event handling is required.
- Environment Setup: Ensure you have PHP, Composer, Node.js, and npm/yarn installed on your machine.
Part 1: Setting Up the Laravel Backend
Introduction
In this part, we will set up the backend for our custom e-commerce platform using Laravel. We'll focus on creating the necessary models, migrations, and API endpoints that will serve as the foundation for our platform. By the end of this section, you'll have a fully functional backend ready to communicate with the frontend.
Step 1: Creating a New Laravel Project
Start by setting up a new Laravel project. Laravel provides a robust framework with built-in tools that make it ideal for developing complex applications like an e-commerce platform.
Open your terminal and run the following command to create a new Laravel project:
composer create-project --prefer-dist laravel/laravel ecommerce-platform
cd ecommerce-platform
After the project is set up, navigate into the project directory.
Step 2: Configuring the Database
Next, you'll need to configure your database settings. Laravel uses environment variables to manage configuration, so you'll need to update the .env
file in your project root.
Open .env
and update the database configuration:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ecommerce
DB_USERNAME=root
DB_PASSWORD=secret
Make sure to replace DB_USERNAME
and DB_PASSWORD
with your actual database credentials.
After configuring the database, you can run the migration command to set up the default tables that Laravel provides, such as users
, password_resets
, etc.
php artisan migrate
Step 3: Defining the E-commerce Database Schema
Now let's define the core database schema for our e-commerce platform. We'll start by creating three essential models: Product
, Category
, and Order
. These models will represent the main entities in our e-commerce platform.
Generate the models and migrations using the following commands:
php artisan make:model Product -m
php artisan make:model Category -m
php artisan make:model Order -m
This will create the model files in the app/Models
directory and the corresponding migration files in the database/migrations
directory.
Updating the Migrations
Next, update the migration files to define the database schema.
Products Table:
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description');
$table->decimal('price', 8, 2);
$table->unsignedBigInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
}
Categories Table:
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
Orders Table:
public function up()
{
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('product_id');
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->integer('quantity');
$table->decimal('total_price', 8, 2);
$table->timestamps();
});
}
These tables will store the information needed for managing products, categories, and customer orders.
Run the migrations to create these tables in your database:
php artisan migrate
Step 4: Setting Up Eloquent Relationships
To link these tables together, you'll define relationships between the models in Laravel. Eloquent, Laravel's ORM, makes it easy to define these relationships.
Product Model:
In app/Models/Product.php
, define the relationship between Product
and Category
as well as Product
and Order
:
public function category()
{
return $this->belongsTo(Category::class);
}
public function orders()
{
return $this->hasMany(Order::class);
}
Category Model:
In app/Models/Category.php
, define the relationship between Category
and Product
:
public function products()
{
return $this->hasMany(Product::class);
}
Order Model:
In app/Models/Order.php
, define the relationship between Order
and Product
:
public function product()
{
return $this->belongsTo(Product::class);
}
These relationships will allow you to easily query related data, such as fetching all products within a category or all orders for a product.
Step 5: Creating API Endpoints
To interact with the frontend, we'll create RESTful API endpoints. These endpoints will allow the frontend to retrieve, create, update, and delete products, categories, and orders.
Define the routes in routes/api.php
:
use App\Http\Controllers\ProductController;
use App\Http\Controllers\CategoryController;
use App\Http\Controllers\OrderController;
Route::get('/products', [ProductController::class, 'index']);
Route::get('/products/{id}', [ProductController::class, 'show']);
Route::post('/products', [ProductController::class, 'store']);
Route::put('/products/{id}', [ProductController::class, 'update']);
Route::delete('/products/{id}', [ProductController::class, 'destroy']);
Route::get('/categories', [CategoryController::class, 'index']);
Route::post('/categories', [CategoryController::class, 'store']);
Route::post('/orders', [OrderController::class, 'store']);
Next, implement the controller methods for handling these routes.
ProductController:
public function index()
{
return Product::with('category')->get();
}
public function show($id)
{
return Product::with('category')->findOrFail($id);
}
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required',
'description' => 'required',
'price' => 'required|numeric',
'category_id' => 'required|exists:categories,id',
]);
return Product::create($validated);
}
public function update(Request $request, $id)
{
$product = Product::findOrFail($id);
$validated = $request->validate([
'name' => 'required',
'description' => 'required',
'price' => 'required|numeric',
'category_id' => 'required|exists:categories,id',
]);
$product->update($validated);
return $product;
}
public function destroy($id)
{
Product::findOrFail($id)->delete();
return response()->noContent();
}
CategoryController:
public function index()
{
return Category::all();
}
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|unique:categories',
]);
return Category::create($validated);
}
OrderController:
public function store(Request $request)
{
$validated = $request->validate([
'product_id' => 'required|exists:products,id',
'quantity' => 'required|integer|min:1',
]);
$product = Product::findOrFail($validated['product_id']);
$totalPrice = $product->price * $validated['quantity'];
$order = Order::create([
'product_id' => $validated['product_id'],
'quantity' => $validated['quantity'],
'total_price' => $totalPrice,
]);
return $order;
}
These methods will handle the API requests for products, categories, and orders, ensuring that the frontend can interact with the backend effectively.
Conclusion of Part 1
At this point, you've successfully set up the backend for your custom e-commerce platform using Laravel. You've defined the database schema, established relationships between models, and created API endpoints to interact with your data. In the next part of this tutorial, we'll focus on setting up the Vue.js frontend and connecting it to this backend.
---Feel free to take a break here before moving on to Part 2, where we will dive into setting up the Vue.js frontend for our e-commerce platform.
Part 2: Setting Up the Vue.js Frontend
Introduction
In Part 2 of this tutorial, we'll focus on setting up the frontend for our e-commerce platform using Vue.js. We'll create a user-friendly interface that interacts with the Laravel backend we set up in Part 1. By the end of this section, you'll have a basic but functional frontend that can display products, view product details, and add items to a shopping cart.
Step 1: Setting Up Vue.js in Laravel
Laravel supports Vue.js out of the box, so integrating Vue into your Laravel project is straightforward. First, ensure that you have Node.js and npm installed on your system.
To begin, navigate to your Laravel project directory and install the necessary dependencies:
npm install vue@next vue-router@next vuex@next axios
Next, set up your Vue environment. Laravel provides a resources/js
directory where you can store your Vue components and other frontend-related files.
Create a new vue.config.js
file in the root directory of your project. This file is used to configure the Vue build process:
module.exports = {
outputDir: '../public',
publicPath: '/',
filenameHashing: false,
};
This configuration ensures that your Vue assets are correctly output to the public
directory, where Laravel can serve them.
Step 2: Organizing the Vue.js Project Structure
To keep your project organized, create the following directory structure inside resources/js
:
resources/js/
├── components/
│ ├── ProductList.vue
│ ├── ProductDetail.vue
│ └── Cart.vue
├── store/
│ └── index.js
└── views/
├── Home.vue
└── Product.vue
Here’s what each directory and file will be used for:
- components/: This directory contains reusable Vue components such as
ProductList.vue
andProductDetail.vue
.
- store/: This directory will contain the Vuex store, which manages the state of your application.
- views/: This directory contains the main pages or views of your application, such as the Home and Product pages.
Step 3: Setting Up Vue Router
Vue Router is the official router for Vue.js, enabling navigation between different views of your application. To set it up, create a new file named router.js
inside the resources/js
directory:
// resources/js/router.js
import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';
import Product from './views/Product.vue';
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/product/:id',
name: 'Product',
component: Product,
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
This configuration defines two routes: the home page (/
) and the product detail page (/product/:id
). The createWebHistory()
function enables HTML5 history mode, providing clean URLs without hash symbols.
Step 4: Setting Up the Vuex Store
Vuex is a state management library for Vue.js, which allows you to manage the state of your application in a centralized store. This is especially useful for managing data like the shopping cart.
Create a new file named index.js
inside the store
directory:
// resources/js/store/index.js
import { createStore } from 'vuex';
const store = createStore({
state: {
cart: [],
},
mutations: {
addToCart(state, product) {
const item = state.cart.find((item) => item.id === product.id);
if (item) {
item.quantity += 1;
} else {
state.cart.push({ ...product, quantity: 1 });
}
},
},
actions: {
addToCart({ commit }, product) {
commit('addToCart', product);
},
},
getters: {
cartItems(state) {
return state.cart;
},
cartTotal(state) {
return state.cart.reduce((total, item) => total + item.price * item.quantity, 0);
},
},
});
export default store;
This store manages the shopping cart state. It includes:
- state: Contains the cart array, where each item represents a product added to the cart.
- mutations: Methods to mutate the state. For example,
addToCart
adds a product to the cart or increases the quantity if it’s already in the cart.
- actions: Functions that commit mutations. The
addToCart
action dispatches the mutation to add a product to the cart.
- getters: Computed properties for the state. For instance,
cartItems
returns all items in the cart, andcartTotal
calculates the total price of the items in the cart.
Step 5: Implementing Vue Components
Next, let's create the core Vue components for our e-commerce platform.
ProductList.vue:
<template>
<div>
<h1>Products</h1>
<div v-for="product in products" :key="product.id">
<h2>{{ product.name }}</h2>
<p>{{ product.description }}</p>
<p>{{ product.price }}</p>
<router-link :to="`/product/${product.id}`">View Details</router-link>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
products: [],
};
},
created() {
axios.get('/api/products').then((response) => {
this.products = response.data;
});
},
};
</script>
ProductDetail.vue:
<template>
<div>
<h1>{{ product.name }}</h1>
<p>{{ product.description }}</p>
<p>{{ product.price }}</p>
<button @click="addToCart">Add to Cart</button>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
product: null,
};
},
created() {
axios.get(`/api/products/${this.$route.params.id}`).then((response) => {
this.product = response.data;
});
},
methods: {
addToCart() {
this.$store.commit('addToCart', this.product);
},
},
};
</script>
Cart.vue:
<template>
<div>
<h1>Shopping Cart</h1>
<div v-for="item in cart" :key="item.id">
<h2>{{ item.name }}</h2>
<p>Quantity: {{ item.quantity }}</p>
<p>Total Price: {{ item.quantity * item.price }}</p>
</div>
<h3>Total: {{ cartTotal }}</h3>
</div>
</template>
<script>
export default {
computed: {
cart() {
return this.$store.getters.cartItems;
},
cartTotal() {
return this.$store.getters.cartTotal;
},
},
};
</script>
These components provide a simple interface for browsing products, viewing product details, and managing the shopping cart.
Step 6: Integrating Vue with Laravel
Finally, you need to integrate your Vue frontend with the Laravel backend.
In your resources/js/app.js
file, set up Vue, Vue Router, and Vuex:
import { createApp } from 'vue';
import router from './router';
import store from './store';
import App from './App.vue';
createApp(App)
.use(router)
.use(store)
.mount('#app');
Update your resources/views/welcome.blade.php
to include the root element for Vue:
<div id="app"></div>
<script src="{{ mix('js/app.js') }}"></script>
Build your assets:
npm run dev
Now, when you visit your Laravel application, you should see the Vue.js frontend integrated and functioning.
Conclusion of Part 2
You've successfully set up the Vue.js frontend for your e-commerce platform and connected it to your Laravel backend. You now have a basic but functional interface where users can browse products, view product details, and manage their shopping cart.
In the next part of this tutorial, we'll enhance the platform by adding features such as user authentication, order processing, and improving the UI/UX with more advanced Vue.js features.
---You can now proceed to Part 3, where we will continue building on the foundation we've created so far.
Part 3: Enhancing the E-commerce Platform
Introduction
In this final part of the tutorial, we'll focus on adding advanced features to our e-commerce platform, such as user authentication, order processing, and improving the overall user interface and user experience. By the end of this part, you'll have a more complete and polished e-commerce application that can be further customized and scaled according to your needs.
Step 1: Implementing User Authentication
To add user authentication, we will use Laravel's built-in authentication system, which provides a straightforward way to handle user registration, login, and logout.
Setting Up Authentication in Laravel
Run the following command to create authentication scaffolding:
composer require laravel/ui
php artisan ui vue --auth
npm install && npm run dev
This command sets up authentication routes, controllers, and views. It also installs Vue.js and integrates the necessary frontend components.
Run the migrations to create the users table:
php artisan migrate
Modifying the Frontend for Authentication
Ensure that the login and registration views are correctly integrated into your Vue.js application.
You can modify the resources/views/layouts/app.blade.php
to include Vue components for login and registration if you prefer a more Vue-centric approach. However, for simplicity, Laravel’s default blade templates can be used.
To protect routes that require authentication, you can modify your Vue Router configuration in router.js
:
import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';
import Product from './views/Product.vue';
import Login from './views/Login.vue';
import Register from './views/Register.vue';
import Cart from './components/Cart.vue';
const routes = [
{ path: '/', name: 'Home', component: Home },
{ path: '/product/:id', name: 'Product', component: Product },
{ path: '/login', name: 'Login', component: Login },
{ path: '/register', name: 'Register', component: Register },
{ path: '/cart', name: 'Cart', component: Cart, meta: { requiresAuth: true } },
];
const router = createRouter({
history: createWebHistory(),
routes,
});
router.beforeEach((to, from, next) => {
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
const isAuthenticated = !!localStorage.getItem('auth_token'); // Assuming you're storing the auth token in localStorage
if (requiresAuth && !isAuthenticated) {
next('/login');
} else {
next();
}
});
export default router;
This ensures that certain routes, like the cart page, are only accessible to authenticated users.
Step 2: Adding Order Processing
Now that we have user authentication in place, we can implement order processing. This involves creating a checkout flow where users can review their cart, provide payment details, and place orders.
Extending the Order Model
Update the Order
model to include user relationships and payment details:
// In app/Models/Order.php
public function user()
{
return $this->belongsTo(User::class);
}
Update the orders
migration file to include user_id
and status
fields:
public function up()
{
Schema::table('orders', function (Blueprint $table) {
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('status')->default('pending');
});
}
Run the migration to update the database schema:
php artisan migrate
Creating the Checkout Component
Create a Checkout.vue
component in resources/js/components/Checkout.vue
:
<template>
<div>
<h1>Checkout</h1>
<div v-for="item in cart" :key="item.id">
<h2>{{ item.name }}</h2>
<p>Quantity: {{ item.quantity }}</p>
<p>Total Price: {{ item.quantity * item.price }}</p>
</div>
<h3>Total: {{ cartTotal }}</h3>
<button @click="placeOrder">Place Order</button>
</div>
</template>
<script>
export default {
computed: {
cart() {
return this.$store.getters.cartItems;
},
cartTotal() {
return this.$store.getters.cartTotal;
},
},
methods: {
placeOrder() {
axios.post('/api/orders', {
user_id: this.$store.state.user.id, // Assuming user info is stored in Vuex
items: this.cart,
total_price: this.cartTotal,
}).then(() => {
this.$router.push('/orders');
});
},
},
};
</script>
This component allows users to review their cart and place an order. Upon clicking "Place Order," the order is submitted to the backend.
Updating the OrderController
In OrderController
, update the store
method to handle the new order structure:
public function store(Request $request)
{
$validated = $request->validate([
'user_id' => 'required|exists:users,id',
'items' => 'required|array',
'total_price' => 'required|numeric',
]);
$order = Order::create([
'user_id' => $validated['user_id'],
'total_price' => $validated['total_price'],
'status' => 'pending',
]);
foreach ($validated['items'] as $item) {
// Assuming OrderItem is a pivot table or related model
$order->items()->create([
'product_id' => $item['id'],
'quantity' => $item['quantity'],
'price' => $item['price'],
]);
}
return $order;
}
This method creates an order and associates it with the authenticated user and the items in their cart.
Step 3: Improving UI/UX
To provide a better user experience, let's add some final touches to the UI using Vue.js components and animations.
Adding Notifications
Integrate a notification system using Vue Toasted:
npm install vue-toasted
In resources/js/app.js
, register Vue Toasted:
import Toasted from 'vue-toasted';
createApp(App)
.use(router)
.use(store)
.use(Toasted, { duration: 3000 })
.mount('#app');
Now, you can add notifications for actions like adding items to the cart or placing an order:
methods: {
addToCart() {
this.$store.commit('addToCart', this.product);
this.$toasted.show('Product added to cart!', { type: 'success' });
},
placeOrder() {
axios.post('/api/orders', {
user_id: this.$store.state.user.id,
items: this.cart,
total_price: this.cartTotal,
}).then(() => {
this.$router.push('/orders');
this.$toasted.show('Order placed successfully!', { type: 'success' });
});
},
},
Adding Animations
To make the UI more interactive, add animations using Vue's built-in transition component:
<template>
<transition name="fade">
<div v-if="showCart">
<Cart />
</div>
</transition>
</template>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
opacity: 0;
}
</style>
These simple animations can greatly enhance the user experience by making the interface feel more responsive.
Step 4: Deploying the Application
Finally, it's time to deploy your application. Ensure that your environment is ready by doing the following:
- Production Build: Create a production build of your Vue.js application:
npm run build
- Laravel Configuration: Ensure that your
.env
file is set up for production, including database, caching, and queue settings.
- Server Setup: Deploy the Laravel application to a server (e.g., using Laravel Forge, DigitalOcean, or another hosting service). Make sure to configure the web server (like Nginx) to serve the Laravel application correctly.
- Deploying Static Assets: Ensure that your built Vue.js assets are served correctly by your web server.
Conclusion of Part 3
Congratulations! You've successfully built and enhanced a custom e-commerce platform using Laravel and Vue.js. This platform includes essential features like user authentication, product management, a shopping cart, and order processing, all wrapped in a responsive and interactive UI.
While the application is now functional, there is always room for improvement. You could extend this platform by adding more features like payment gateways, inventory management, product reviews, and more.
---
Comments
Please log in to leave a comment.