Clothing Shop là website thương mại điện tử đơn giản bán các mặt hàng thời trang như váy, bikini, đồ hè, đồ mặc đi biển,… Dự án được phát triển bằng Laravel Framework với thiết kế hiện đại, dễ sử dụng và tích hợp các công nghệ phổ biến:
| Công nghệ | Mô tả | |——————|—————————————————-| | Laravel | Framework PHP chính | | Laravel Breeze | Xác thực người dùng, session | | Blade + Bootstrap| Giao diện người dùng hiện đại | | Eloquent ORM | Truy vấn và thao tác dữ liệu theo mô hình OOP | | MySQL (Aiven) | Cơ sở dữ liệu trực tuyến (cloud database) | | Middleware | Phân quyền, kiểm tra truy cập, CSRF token | —
—
—
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = [
'product_name',
'product_price',
'product_image',
];
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\Product;
class Cart extends Model
{
protected $table = 'cart';
protected $fillable = ['user_id', 'product_id', 'quantity'];
// Quan hệ: 1 Cart thuộc về 1 Product
public function product()
{
return $this->belongsTo(Product::class);
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
protected $fillable = [
'user_id', 'name', 'phone', 'email', 'address', 'note',
'delivery_method', 'payment_method', 'total', 'status'
];
public function orderItems()
{
return $this->hasMany(OrderItem::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
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);
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Product;
class ProductController extends Controller
{
public function index() {
$products = Product::all();
return view('admin.all_product', compact('products'));
}
public function create() {
return view('admin.add_product');
}
public function store(Request $request)
{
$product = new Product();
$product->product_name = $request->input('product_name');
$product->product_price = $request->input('product_price');
if ($request->hasFile('product_image')) {
$image = $request->file('product_image');
$imageName = time() . '_' . $image->getClientOriginalName();
$image->move(public_path('uploads/product'), $imageName);
$product->product_image = $imageName;
}
$product->save();
return redirect('/admin/products')->with('success', 'Thêm sản phẩm thành công');
}
public function edit($id) {
$product = Product::findOrFail($id);
return view('admin.edit_product', compact('product'));
}
public function update(Request $request, $id)
{
$product = Product::findOrFail($id);
$product->product_name = $request->input('product_name');
$product->product_price = $request->input('product_price');
if ($request->hasFile('product_image')) {
$image = $request->file('product_image');
$imageName = time() . '_' . $image->getClientOriginalName();
$image->move(public_path('uploads/product'), $imageName);
$product->product_image = $imageName;
}
$product->save();
return redirect('/admin/products')->with('success', 'Cập nhật thành công');
}
public function destroy($id) {
Product::destroy($id);
return redirect('/admin/products');
}
public function showProducts()
{
$products = Product::all();
return view('pages.Product', compact('products'));
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\Product;
class AdminController extends Controller
{
public function showLoginForm()
{
return view('admin.login');
}
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
if (auth()->user()->is_admin) {
return redirect()->route('admin.dashboard');
}
Auth::logout();
return back()->withErrors(['email' => 'Bạn không có quyền vào admin']);
}
return back()->withErrors(['email' => 'Thông tin đăng nhập không hợp lệ']);
}
public function dashboard()
{
$products = Product::all();
return view('admin.dashboard', compact('products'));
if (!Auth::check()) {
return redirect()->route('admin.login');
}
return view('admin.dashboard');
}
}
<?php
namespace App\Http\Controllers;
use App\Models\Cart;
use App\Models\Product;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use App\Models\Order;
use App\Models\OrderItem;
class CartController extends Controller
{
public function addToCart($id)
{
$cart = Cart::where('user_id', Auth::id())
->where('product_id', $id)
->first();
if ($cart) {
$cart->quantity += 1;
$cart->save();
} else {
Cart::create([
'user_id' => Auth::id(),
'product_id' => $id,
'quantity' => 1,
]);
}
return redirect()->back()->with('success', 'Đã thêm vào giỏ hàng!');
}
public function removeFromCart($id)
{
$cart = Cart::find($id);
if ($cart && $cart->user_id == Auth::id()) {
$cart->delete();
}
return redirect()->route('cart.view')->with('success', 'Đã xóa sản phẩm');
}
public function viewCart()
{
$cartItems = Cart::where('user_id', Auth::id())->with('product')->get();
$total = 0;
foreach ($cartItems as $item) {
$total += $item->product->product_price * $item->quantity;
}
return view('pages.cart', compact('cartItems', 'total'));
}
public function updateQuantity(Request $request)
{
foreach ($request->cart_ids as $index => $id) {
$cart = Cart::find($id);
if ($cart && $cart->user_id == Auth::id()) {
$cart->quantity = $request->quantities[$index];
$cart->save();
}
}
return redirect()->back()->with('success', 'Đã cập nhật số lượng');
}
public function checkout()
{
$cartItems = Cart::where('user_id', Auth::id())->with('product')->get();
$total = 0;
foreach ($cartItems as $item) {
$total += $item->product->product_price * $item->quantity;
}
return view('pages.checkout', compact('cartItems', 'total'));
}
public function ajaxUpdateQuantity(Request $request)
{
$cart = Cart::find($request->cart_id);
if ($cart && $cart->user_id == Auth::id()) {
$cart->quantity = $request->quantity;
$cart->save();
return response()->json(['success' => true]);
}
return response()->json(['success' => false], 403);
}
public function processCheckout(Request $request)
{
$request->validate([
'address' => 'required|string|max:255',
'payment_method' => 'required|string',
]);
$cartItems = Cart::with('product')->where('user_id', Auth::id())->get();
$total = $cartItems->sum(fn($item) => $item->product->product_price * $item->quantity);
$order = Order::create([
'user_id' => Auth::id(),
'address' => $request->address,
'payment_method' => $request->payment_method,
'total' => $total,
]);
foreach ($cartItems as $item) {
OrderItem::create([
'order_id' => $order->id,
'product_id' => $item->product_id,
'quantity' => $item->quantity,
'price' => $item->product->product_price,
]);
}
Cart::where('user_id', Auth::id())->delete();
return redirect()->route('cart.view')->with('success', 'Đơn hàng đã được đặt thành công!');
}
public function placeOrder(Request $request)
{
return redirect('/')->with('success', 'Đặt hàng thành công!');
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Cart;
use App\Models\Order;
use App\Models\OrderItem;
use Illuminate\Support\Facades\Auth;
class OrderController extends Controller
{
// Hàm xử lý thanh toán
public function checkout()
{
// Lấy danh sách sản phẩm trong giỏ hàng
$cartItems = Cart::with('product')->where('user_id', Auth::id())->get();
// Nếu giỏ hàng trống
if ($cartItems->isEmpty()) {
return redirect()->back()->with('error', 'Giỏ hàng của bạn đang trống.');
}
// Tính tổng tiền
$total = 0;
foreach ($cartItems as $item) {
$total += $item->product->product_price * $item->quantity;
}
// Tạo đơn hàng mới
$order = Order::create([
'user_id' => Auth::id(),
'total' => $total,
]);
// Tạo các mục trong đơn hàng
foreach ($cartItems as $item) {
OrderItem::create([
'order_id' => $order->id,
'product_id' => $item->product_id,
'quantity' => $item->quantity,
'price' => $item->product->product_price,
]);
}
// Xóa giỏ hàng sau khi thanh toán
Cart::where('user_id', Auth::id())->delete();
// Redirect với thông báo
return redirect()->route('cart.view')->with('success', 'Đặt hàng thành công!');
}
public function placeOrder(Request $request)
{
$cartItems = Cart::where('user_id', Auth::id())->with('product')->get();
if ($cartItems->isEmpty()) {
return redirect()->back()->with('error', 'Giỏ hàng trống!');
}
// 1. Tạo đơn hàng
$order = Order::create([
'user_id' => Auth::id(),
'name' => $request->name,
'phone' => $request->phone,
'email' => $request->email,
'address' => $request->address,
'note' => $request->note,
'delivery_method' => $request->delivery_method,
'total' => $cartItems->sum(fn($item) => $item->product->product_price * $item->quantity) + 20000,
]);
// 2. Tạo từng sản phẩm trong đơn
foreach ($cartItems as $item) {
OrderItem::create([
'order_id' => $order->id,
'product_id' => $item->product->id,
'quantity' => $item->quantity,
'price' => $item->product->product_price,
]);
}
// 3. Xoá giỏ hàng
Cart::where('user_id', Auth::id())->delete();
// 4. Chuyển hướng kèm thông báo
return redirect()->route('order.history')->with('success', 'Đặt hàng thành công!');
}
public function orderHistory()
{
$orders = Order::where('user_id', Auth::id())->with('orderItems.product')->get();
return view('pages.order_history', compact('orders'));
}
}
<?php
use App\Http\Controllers\ProfileController;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;
use App\Http\Controllers\AdminController;
use App\Http\Controllers\CartController;
use App\Http\Controllers\OrderController;
use App\Http\Controllers\AdminOrderController;
Route::get('/', function () {
return view('welcome');
});
Route::get('/trang-chu', function () {
return view('welcome');
});
Route::get('/dashboard', function () {
abort(403, 'Không có quyền truy cập.');
})->middleware(['auth', 'verified', 'admin']);
Route::get('/dashboard', function () {
return redirect('/san-pham');
})->middleware(['auth'])->name('dashboard');
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
// backend
Route::get('/admin/login', [AdminController::class, 'showLoginForm'])->name('admin.login');
Route::post('/admin/login', [AdminController::class, 'login'])->name('admin.login.post');
// product
Route::get('/admin/dashboard', [AdminController::class, 'dashboard'])->name('admin.dashboard');
Route::get('/admin/products', [ProductController::class, 'index']);
Route::get('/admin/products/create', [ProductController::class, 'create']);
Route::post('/admin/products', [ProductController::class, 'store']);
Route::get('/admin/products/{id}/edit', [ProductController::class, 'edit']);
Route::post('/admin/products/{id}/update', [ProductController::class, 'update']);
Route::get('/admin/products/{id}/delete', [ProductController::class, 'destroy']);
Route::get('/admin/orders', [AdminOrderController::class, 'index']);
// admin them san pham
Route::get('/san-pham', [ProductController::class, 'showProducts']);
require __DIR__.'/auth.php';
// cart
Route::post('/them-gio-hang/{id}', [CartController::class, 'addToCart'])->middleware('auth')->name('cart.add');
Route::get('/gio-hang', [CartController::class, 'viewCart'])->name('cart.view');
Route::get('/gio-hang/xoa/{id}', [CartController::class, 'removeFromCart'])->name('cart.remove');
Route::post('/gio-hang/cap-nhat', [CartController::class, 'updateQuantity'])->name('cart.update');
Route::get('/thanh-toan', [CartController::class, 'checkout'])->name('cart.checkout');
Route::post('/cart/update-quantity', [CartController::class, 'ajaxUpdateQuantity'])->name('cart.ajax.update');
// checkout
Route::get('/thanh-toan', [CartController::class, 'checkout']);
//Route::get('/thanh-toan', [CartController::class, 'checkoutForm'])->name('cart.checkout');
Route::post('/thanh-toan', [CartController::class, 'processCheckout'])->name('cart.processCheckout');
Route::post('/dat-hang', [OrderController::class, 'placeOrder'])->name('order.place');
Route::get('/thanh-toan', [CartController::class, 'checkout'])->name('cart.checkout');
Route::get('/gio-hang', [CartController::class, 'viewCart'])->name('cart.show');
// lich su don hang
Route::post('/dat-hang', [OrderController::class, 'placeOrder'])->name('order.place');
Route::get('/lich-su-don-hang', [OrderController::class, 'orderHistory'])->name('order.history');
Route::put('/admin/orders/{id}/approve', [AdminOrderController::class, 'approve']);
Route::delete('/admin/orders/{id}', [AdminOrderController::class, 'destroy']);
<form method="POST" action="" enctype="multipart/form-data">
@csrf
<div class="mb-3">
<label for="product_name" class="form-label">Tên sản phẩm</label>
<input type="text" class="form-control" name="product_name" id="product_name" required>
</div>
$request->validate([
'address' => 'required|string|max:255',
'payment_method' => 'required|string',
]);
<div style="padding-left: 10px;">
@foreach ($order->orderItems as $item)
<div style="display: flex; align-items: center; gap: 15px; margin-bottom: 10px;">
<img src="" alt="" width="60" height="60" style="border-radius: 6px; border: 1px solid #ddd;">
<div>
<p style="margin: 0;"><strong></strong></p>
<p style="margin: 0;">SL: x đ</p>
</div>
</div>
@endforeach
</div>
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
if (auth()->user()->is_admin) {
return redirect()->route('admin.dashboard');
}
Auth::logout();
return back()->withErrors(['email' => 'Bạn không có quyền vào admin']);
}
return back()->withErrors(['email' => 'Thông tin đăng nhập không hợp lệ']);
}
public function handle(Request $request, Closure $next)
{
if (auth()->check() && auth()->user()->is_admin) {
return $next($request);
}
return redirect('/'); // hoặc abort(403);
}
🔒 Đăng nhập :
🔒 Đăng ký :
Trang chủ :
Trang sản phẩm :
Trang giỏ hàng :
Trang thanh toán :
Trang dashboard :
Trang quản lý sản phẩm ( CRUD product ) :
Trang quản lý đơn hàng :
License & Copy Rights
The Laravel framework is open-sourced software licensed under the MIT license.