今天是鐵人賽 Day19,目標是建立購物車 API,讓會員能夠新增商品到購物車、修改數量,以及刪除商品。
1️⃣ 後端 Cart Model (Cart.js
)
今天確認購物車 Schema,包含使用者 ID、商品陣列與數量,確保每個會員都有自己的購物車:
const mongoose = require('mongoose');
const cartSchema = new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
items: [
{
productId: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true },
quantity: { type: Number, default: 1 }
}
],
createdAt: { type: Date, default: Date.now }
});
module.exports = mongoose.model('Cart', cartSchema);
2️⃣ 購物車 API (cartRoutes.js
)
今天建立購物車路由,包含四個功能:
GET /api/cart/
POST /api/cart/add
PUT /api/cart/update
DELETE /api/cart/remove/:productId
const express = require('express');
const router = express.Router();
const Cart = require('../models/Cart');
const { authMiddleware } = require('../middleware/authMiddleware');
const mongoose = require('mongoose');
// 取得購物車
router.get('/', authMiddleware, async (req, res) => {
const cart = await Cart.findOne({ userId: req.user.id }).populate('items.productId', 'name price');
res.json(cart || { items: [] });
});
// 新增商品
router.post('/add', authMiddleware, async (req, res) => {
const { productId, quantity } = req.body;
let cart = await Cart.findOne({ userId: req.user.id });
if (!cart) {
cart = new Cart({ userId: req.user.id, items: [{ productId, quantity }] });
} else {
const index = cart.items.findIndex(item => item.productId.toString() === productId);
if (index > -1) cart.items[index].quantity += quantity;
else cart.items.push({ productId, quantity });
}
await cart.save();
res.json(cart);
});
// 修改商品數量
router.put('/update', authMiddleware, async (req, res) => {
const { productId, quantity } = req.body;
const cart = await Cart.findOne({ userId: req.user.id });
const index = cart.items.findIndex(item => item.productId.toString() === productId);
if (quantity <= 0) cart.items.splice(index, 1);
else cart.items[index].quantity = quantity;
await cart.save();
res.json(cart);
});
// 刪除商品
router.delete('/remove/:productId', authMiddleware, async (req, res) => {
const { productId } = req.params;
const cart = await Cart.findOne({ userId: req.user.id });
cart.items = cart.items.filter(item => item.productId.toString() !== productId);
await cart.save();
res.json(cart);
});
module.exports = router;
3️⃣ 後端整合 (index.js
)
將購物車路由掛載到後端主程式,與會員與商品路由一起運作:
app.use('/api/products', productRoutes);
app.use('/api/auth', userRoutes);
app.use('/api/cart', cartRoutes);
4️⃣ 測試流程
會員登入 → 使用 POST /api/cart/add
新增商品
使用 GET /api/cart/
查看購物車
修改商品數量 → PUT /api/cart/update
刪除商品 → DELETE /api/cart/remove/:productId
🐛 遇到的問題與解決
問題:購物車尚未建立,會員新增商品時找不到對應資料
解決:建立 Cart Model,並在新增商品時檢查是否已存在購物車,如果沒有則自動創建
💡 Day19 收穫