本系列示範一個輕量級購物車:後端用 PHP Session 儲存、前端用 jQuery + Thickbox 彈窗實現無刷新加入/編輯/刪除。本文為第一部分,涵蓋核心類別、動作處理器、首頁與購物車頁面。
Shopping_Cart 類別:封裝 Session 存取、商品增刪改查、價格/名稱虛擬方法。cart_action.php:接收 AJAX/iframe 請求,操作購物車並導向購物車頁。index.html:商品列表頁,表單送出至 Thickbox 彈窗。cart.php:購物車內容頁,支援數量修改、刪除、小計顯示。<?php
// Shopping_Cart.class.php
class Shopping_Cart {
private $cartName;
private $items = [];
public function __construct($name = 'shopping_cart') {
$this->cartName = $name;
session_start();
$this->items = $_SESSION[$this->cartName] ?? [];
}
public function setItemQuantity($orderCode, $quantity) {
if ($quantity <= 0) {
unset($this->items[$orderCode]);
} else {
$this->items[$orderCode] = (int)$quantity;
}
}
public function getItemQuantity($orderCode) {
return (int)($this->items[$orderCode] ?? 0);
}
public function getItems() {
return $this->items;
}
public function hasItems() {
return !empty($this->items);
}
// 虛擬方法:實際專案應查詢資料庫
public function getItemPrice($orderCode) {
return 9.99; // 統一價格示範
}
public function getItemName($orderCode) {
return "商品 {$orderCode}";
}
public function save() {
$_SESSION[$this->cartName] = $this->items;
}
}
<?php
// cart_action.php
require_once 'Shopping_Cart.class.php';
session_start();
$cart = new Shopping_Cart();
if (isset($_GET['order_code'])) {
// 單一商品加入/修改
$code = $_GET['order_code'];
$qty = max(1, (int)($_GET['quantity'] ?? 1));
$cart->setItemQuantity($code, $cart->getItemQuantity($code) + $qty);
} else {
// 批次更新(來自購物車頁面表單)
if (!empty($_GET['quantity'])) {
foreach ($_GET['quantity'] as $code => $qty) {
$cart->setItemQuantity($code, (int)$qty);
}
}
if (!empty($_GET['remove'])) {
foreach ($_GET['remove'] as $code) {
$cart->setItemQuantity($code, 0);
}
}
}
$cart->save();
// Thickbox 模式:導回父頁面的購物車頁
header('Location: cart.php?KeepThis=true&TB_iframe=true&height=400&width=780');
exit;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>商品列表</title>
<script src="js/jquery-1.12.4.min.js"></script>
<script src="js/thickbox.js"></script>
<link href="css/thickbox.css" rel="stylesheet">
<script>
$(function() {
// 表單送出 -> 開啟 Thickbox 彈窗處理
$('form.cart_form').on('submit', function(e) {
e.preventDefault();
var $form = $(this);
var code = $form.find('[name=order_code]').val();
var qty = $form.find('[name=quantity]').val();
var url = 'cart_action.php?order_code=' + code + '&quantity=' + qty
+ '&TB_iframe=true&height=400&width=780';
tb_show('購物車', url, false);
});
});
</script>
</head>
<body>
<div id="container">
<h1>商品列表</h1>
<a href="cart.php?KeepThis=true&TB_iframe=true&height=400&width=780" class="thickbox" title="購物車">
🛒 檢視購物車
</a>
<hr>
<form class="cart_form" method="get">
<input type="hidden" name="order_code" value="PROD_001">
<label>產品 A - $9.99
<input type="number" name="quantity" value="1" min="1" size="3">
</label>
<button type="submit">加入購物車</button>
</form>
<hr>
<form class="cart_form" method="get">
<input type="hidden" name="order_code" value="PROD_002">
<label>產品 B - $19.99
<input type="number" name="quantity" value="1" min="1" size="3">
</label>
<button type="submit">加入購物車</button>
</form>
</div>
</body>
</html>
<?php
// cart.php
require_once 'Shopping_Cart.class.php';
session_start();
$cart = new Shopping_Cart();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>購物車</title>
<script src="js/jquery-1.12.4.min.js"></script>
<script src="js/cart.js"></script>
<link href="css/cart.css" rel="stylesheet">
</head>
<body>
<div id="container">
<h1>🛒 購物車</h1>
<?php if ($cart->hasItems()) : ?>
<form action="cart_action.php" method="get">
<table id="cart">
<thead>
<tr><th>數量</th><th>商品</th><th>單價</th><th>小計</th><th>刪除</th></tr>
</thead>
<tbody>
<?php
$total = 0; $i = 0;
foreach ($cart->getItems() as $code => $qty) :
$price = $cart->getItemPrice($code);
$sub = $price * $qty;
$total += $sub;
?>
<tr class="<?= $i++ % 2 ? 'odd' : '' ?>">
<td><input type="number" name="quantity[<?= $code ?>]" value="<?= $qty ?>" min="1" size="3"></td>
<td><?= htmlspecialchars($cart->getItemName($code)) ?></td>
<td>$<?= number_format($price, 2) ?></td>
<td>$<?= number_format($sub, 2) ?></td>
<td><input type="checkbox" name="remove[]" value="<?= $code ?>"></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr><td colspan="3"><strong>總計</strong></td><td>$<?= number_format($total, 2) ?></td><td></td></tr>
</tfoot>
</table>
<button type="submit" name="update">更新購物車</button>
</form>
<?php else : ?>
<p class="empty">購物車是空的 <a href="index.html">去逛逛</a></p>
<?php endif; ?>
</div>
</body>
</html>
// cart.js - 數量變更即時送出(可選)
$('#cart input[name^="quantity"]').on('change', function() {
$(this).closest('form').submit();
});
// 去除 Thickbox 邊框滾動條
$('#TB_window').css('overflow', 'hidden');
| 項目 | 建議 |
|---|---|
| CSRF 防護 | 表單加入 csrf_token,cart_action 驗證 |
| 價格防竄改 | 前端不信任價格,後端從 DB 讀取 |
| 庫存檢查 | 加入/更新時檢查庫存,不足則回滾 |
| 登入整合 | 會員登入後合併 Session 購物車至資料庫 |
| 優惠碼 | 擴充 Cart 類別加入 coupon_code、discount 屬性 |