首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 購物車系統實作:Session 管理、商品增刪改、文字檔資料儲存完整範例

     編輯:PHP 綜合知識

購物車是電商核心功能。本文提供一套不依賴資料庫、以 Session + 文字檔儲存商品資料的完整購物車範例,涵蓋加入商品、顯示購物車、修改數量、移除商品、結帳導向支付頁面等完整流程,程式碼結構清晰,適合中小型專案快速導入或教學參考。

系統架構概覽

檔案功能說明
lib.inc.php商品資料載入從 products.txt 讀取商品主檔
add_item.php加入購物車接收商品 ID、數量,寫入 Session
cart.php購物車頁面顯示明細、修改數量、移除、小計、商品列表
change_quant.php修改數量更新 Session 中商品數量或移除
products.txt商品資料檔每行一筆:id|name|desc|price

商品資料檔 products.txt

P001|iPhone 15 Pro|最新款旗艦手機|35900
P002|MacBook Air M2|13吋輕薄筆電|32900
P003|AirPods Pro 2|主動降噪藍牙耳機|7490
P004|Apple Watch S9|智慧手錶|12900
P005|iPad Air 10.9|平板電腦|19900

核心庫 lib.inc.php

<?php
$master_products_list = [];

function LoadProducts() {
    global $master_products_list;
    $filename = 'products.txt';
    $fp = @fopen($filename, 'r') or die("無法開啟 $filename");
    @flock($fp, LOCK_SH) or die("鎖定失敗");

    while ($line = fgets($fp, 1024)) {
        $line = trim($line);
        if (!$line) continue;
        list($id, $name, $desc, $price) = explode('|', $line);
        $id = trim($id);
        $master_products_list[$id] = [
            'name'  => $name,
            'desc'  => $desc,
            'price' => (float)$price,
        ];
    }
    @fclose($fp);
}
?>

加入商品 add_item.php

<?php
session_start();
require 'lib.inc.php';
LoadProducts();

$prod_id = $_GET['id'] ?? '';
if (!$prod_id || !isset($master_products_list[$prod_id])) {
    die('商品不存在');
}
$product = $master_products_list[$prod_id];

// 初始化購物車 Session
if (!isset($_SESSION['cart'])) {
    $_SESSION['cart'] = ['num_items' => 0, 'products' => []];
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $qty = max(1, (int)($_POST['quantity'] ?? 1));
    // 檢查是否已在購物車
    $found = false;
    foreach ($_SESSION['cart']['products'] as $i => $item) {
        if ($item[0] === $prod_id) {
            $_SESSION['cart']['products'][$i][1] += $qty;
            $found = true;
            break;
        }
    }
    if (!$found) {
        $_SESSION['cart']['products'][] = [$prod_id, $qty];
    }
    $_SESSION['cart']['num_items'] += $qty;

    echo "

{$product['name']} 已加入購物車

"; echo '查看購物車 | 繼續購物'; exit; } ?> <!DOCTYPE html> <html><head><meta charset="utf-8"><title>加入購物車</title></head><body> <h1>加入 <?= htmlspecialchars($product['name']) ?> 到購物車</h1> <p>說明:<?= htmlspecialchars($product['desc']) ?></p> <p>單價:NT$ <?= number_format($product['price']) ?></p> <form method="post"> 數量:<input type="number" name="quantity" value="1" min="1" max="99"> <input type="hidden" name="id" value="<?= $prod_id ?>"> <button type="submit">加入購物車</button> </form> <p><a href="cart.php">返回商品列表</a></p> </body></html>

購物車頁面 cart.php

<?php
session_start();
require 'lib.inc.php';
LoadProducts();

if (!isset($_SESSION['cart'])) {
    $_SESSION['cart'] = ['num_items' => 0, 'products' => []];
}
$cart = &$_SESSION['cart'];

$total = 0;
foreach ($cart['products'] as $item) {
    list($pid, $qty) = $item;
    if (isset($master_products_list[$pid])) {
        $total += $master_products_list[$pid]['price'] * $qty;
    }
}
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>購物車</title>
<style>
table {border-collapse:collapse;width:100%;max-width:800px;margin:1rem auto;}
th,td {border:1px solid #ddd;padding:8px;text-align:center;}
th {background:#f5f5f5;}
.input-qty {width:60px;text-align:center;}
.btn {padding:4px 12px;cursor:pointer;}
</style></head><body>
<h1 style="text-align:center">我的購物車</h1>

<?php if ($cart['num_items'] > 0): ?>
<table>
  <thead>
    <tr><th>商品</th><th>說明</th><th>單價</th><th>數量</th><th>小計</th><th>操作</th></tr>
  </thead>
  <tbody>
    <?php foreach ($cart['products'] as $idx => $item): 
        list($pid, $qty) = $item;
        if (!isset($master_products_list[$pid])) continue;
        $p = $master_products_list[$pid];
        $subtotal = $p['price'] * $qty;
    ?>
    <tr>
      <td><?= htmlspecialchars($p['name']) ?></td>
      <td><?= htmlspecialchars($p['desc']) ?></td>
      <td>NT$ <?= number_format($p['price']) ?></td>
      <td>
        <form action="change_quant.php" method="post" style="display:inline">
          <input type="hidden" name="idx" value="<?= $idx ?>">
          <input type="number" name="quantity" value="<?= $qty ?>" min="0" max="99" class="input-qty">
          <button type="submit" class="btn">更新</button>
        </form>
      </td>
      <td>NT$ <?= number_format($subtotal) ?></td>
      <td>
        <form action="change_quant.php" method="post" style="display:inline" onsubmit="return confirm('確定移除?')">
          <input type="hidden" name="idx" value="<?= $idx ?>">
          <input type="hidden" name="quantity" value="0">
          <button type="submit" class="btn" style="background:#dc3545;color:white">移除</button>
        </form>
      </td>
    </tr>
    <?php endforeach; ?>
    <tr>
      <td colspan="4" style="text-align:right"><strong>總計</strong></td>
      <td><strong>NT$ <?= number_format($total) ?></strong></td>
      <td></td>
    </tr>
  </tbody>
</table>
<div style="text-align:center;margin:1rem">
  <a href="checkout.php" class="btn" style="background:#28a745;color:white;padding:12px 24px;font-size:1.1rem">前往結帳</a>
</div>
<?php else: ?>
<p style="text-align:center;color:#666">購物車是空的</p>
<?php endif; ?>

<hr>
<h2>商品列表</h2>
<table>
  <thead><tr><th>商品</th><th>說明</th><th>單價</th><th>操作</th></tr></thead>
  <tbody>
    <?php foreach ($master_products_list as $pid => $p): ?>
    <tr>
      <td><?= htmlspecialchars($p['name']) ?></td>
      <td><?= htmlspecialchars($p['desc']) ?></td>
      <td>NT$ <?= number_format($p['price']) ?></td>
      <td><a href="add_item.php?id=<?= $pid ?>" class="btn">加入購物車</a></td>
    </tr>
    <?php endforeach; ?>
  </tbody>
</table>
</body></html>

修改數量 change_quant.php

<?php
session_start();
if (!isset($_SESSION['cart'])) {
    header('Location: cart.php');
    exit;
}

$idx = (int)($_POST['idx'] ?? -1);
$new_qty = max(0, (int)($_POST['quantity'] ?? 0));

if ($idx < 0 || $idx >= count($_SESSION['cart']['products'])) {
    header('Location: cart.php');
    exit;
}

$old_qty = $_SESSION['cart']['products'][$idx][1];

if ($new_qty > 0) {
    $_SESSION['cart']['products'][$idx][1] = $new_qty;
    $_SESSION['cart']['num_items'] += ($new_qty - $old_qty);
} else {
    // 數量為 0 視為移除
    array_splice($_SESSION['cart']['products'], $idx, 1);
    $_SESSION['cart']['num_items'] -= $old_qty;
}

header('Location: cart.php');
?>

進階擴充建議

功能實作方向
資料庫儲存建立 cart_items 表,user_id 關聯,支援跨裝置同步
Redis 快取Session 改用 Redis,高併發下效能更佳、支援集群
優惠碼/折扣結帳頁面輸入優惠碼,後端驗證並計算折扣金額
運費計算依地址、重量、金額門檻計算運費,支援多物流商
庫存檢查加入/修改數量時即時檢查庫存,不足時提示
購物車持久化未登入用戶用 Cookie 儲存 cart_id,登入後合併
AJAX 無刷新更新前端 fetch API 更新數量,回傳新總計、小計
商品屬性 (規格)支援顏色、尺寸等 SKU,購物車按 SKU 區分

安全性檢查清單

  • [ ] 所有輸出經 htmlspecialchars() 防 XSS
  • [ ] 價格、庫存等敏感資訊**嚴禁**前端決定,皆以伺服器端資料為準
  • [ ] 數量輸入嚴格 (int) 強制轉型、範圍限制
  • [ ] CSRF Token 保護表單提交 (加入/修改/移除/結帳)
  • [ ] HTTPS 全站強制,保護 Session Cookie
  • [ ] session.cookie_httponly=1, session.cookie_secure=1, session.use_strict_mode=1

此範例展示了購物車的核心邏輯與資料流,實際專案建議採用成熟電商框架 (如 Laravel Shopping Cart、Sylius、Magento) 或依業務規模自行模組化擴展。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved