iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
Modern Web

使用 React + Node.js + MongoDB 打造電商網站系列 第 19

Day19 完成購物車 API:新增、修改數量與刪除商品

  • 分享至 

  • xImage
  •  

今天是鐵人賽 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 收穫

  • 完成購物車 CRUD API
  • 確認購物車與會員綁定
  • 使用 JWT 驗證會員操作安全

上一篇
Day18 會員/管理員登入後導向個人頁面(Profile)
系列文
使用 React + Node.js + MongoDB 打造電商網站19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言