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

PHP 購物車核心類別實作解析:Session 識別、資料庫操作與金額計算

     編輯:PHP 相關知識

前言

購物車是電商系統核心模組。本文解析一個經典的 PHP 購物車類別:使用 Session + Cookie 識別用戶,MySQL 持久化商品明細,提供增刪改查、金額計算、內容顯示等完整功能。

核心設計

  • 識別機制:scid Cookie 存放 Session ID(MD5 唯一值),有效期 4 小時。
  • 資料表結構:cart (id, session, product, quantity) + inventory (product, price, description)。
  • 核心方法:檢查/新增/刪除/修改/清空/總價/明細/商品種類數/總數量。

完整類別代碼

<?php
// Session/Cookie 初始化(放在入口檔案或共用 include)
if (!isset($_COOKIE['scid']) && !isset($_SESSION['scid'])) {
    $session = md5(uniqid(rand(), true));
    setcookie('scid', $session, time() + 14400); // 4 小時
    $_SESSION['scid'] = $session;
} else {
    $session = $_COOKIE['scid'] ?? $_SESSION['scid'];
}

class Cart {
    private $table = 'cart';

    // 檢查商品是否已在購物車
    public function check_item($session, $product) {
        $sql = "SELECT quantity FROM {$this->table} WHERE session=? AND product=?";
        $stmt = $GLOBALS['db']->prepare($sql);
        $stmt->execute([$session, $product]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row ? (int)$row['quantity'] : 0;
    }

    // 新增或增加數量
    public function add_item($session, $product, $quantity) {
        $qty = $this->check_item($session, $product);
        if ($qty == 0) {
            $sql = "INSERT INTO {$this->table} (session, product, quantity) VALUES (?, ?, ?)";
            $GLOBALS['db']->execute($sql, [$session, $product, $quantity]);
        } else {
            $quantity += $qty;
            $sql = "UPDATE {$this->table} SET quantity=? WHERE session=? AND product=?";
            $GLOBALS['db']->execute($sql, [$quantity, $session, $product]);
        }
    }

    // 刪除商品
    public function delete_item($session, $product) {
        $sql = "DELETE FROM {$this->table} WHERE session=? AND product=?";
        $GLOBALS['db']->execute($sql, [$session, $product]);
    }

    // 修改數量
    public function modify_quantity($session, $product, $quantity) {
        $sql = "UPDATE {$this->table} SET quantity=? WHERE session=? AND product=?";
        $GLOBALS['db']->execute($sql, [$quantity, $session, $product]);
    }

    // 清空購物車
    public function clear_cart($session) {
        $sql = "DELETE FROM {$this->table} WHERE session=?";
        $GLOBALS['db']->execute($sql, [$session]);
    }

    // 計算總金額
    public function cart_total($session) {
        $sql = "SELECT c.product, c.quantity, i.price 
                FROM {$this->table} c 
                JOIN inventory i ON c.product = i.product 
                WHERE c.session=?";
        $stmt = $GLOBALS['db']->prepare($sql);
        $stmt->execute([$session]);
        $total = 0;
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $total += $row['price'] * $row['quantity'];
        }
        return $total;
    }

    // 取得詳細明細(含商品資訊)
    public function display_contents($session) {
        $sql = "SELECT c.product, c.quantity, i.price, i.description
                FROM {$this->table} c
                JOIN inventory i ON c.product = i.product
                WHERE c.session=?
                ORDER BY c.id";
        $stmt = $GLOBALS['db']->prepare($sql);
        $stmt->execute([$session]);
        
        $contents = ['product'=>[], 'price'=>[], 'quantity'=>[], 'total'=>[], 'description'=>[]];
        $count = 0;
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $contents['product'][$count]     = $row['product'];
            $contents['price'][$count]       = $row['price'];
            $contents['quantity'][$count]    = $row['quantity'];
            $contents['total'][$count]       = $row['price'] * $row['quantity'];
            $contents['description'][$count] = $row['description'];
            $count++;
        }
        $contents['final'] = $this->cart_total($session);
        return $contents;
    }

    // 商品種類數
    public function num_items($session) {
        $sql = "SELECT COUNT(*) FROM {$this->table} WHERE session=?";
        $stmt = $GLOBALS['db']->prepare($sql);
        $stmt->execute([$session]);
        return $stmt->fetchColumn();
    }

    // 總數量
    public function quant_items($session) {
        $sql = "SELECT SUM(quantity) FROM {$this->table} WHERE session=?";
        $stmt = $GLOBALS['db']->prepare($sql);
        $stmt->execute([$session]);
        return (int)$stmt->fetchColumn();
    }
}
?>

前端調用範例

<?php
require 'Cart.php';
$cart = new Cart();
$session = $_COOKIE['scid'] ?? session_id();

// 加入商品
if (isset($_POST['add_product'])) {
    $cart->add_item($session, $_POST['product_id'], $_POST['qty'] ?? 1);
    header('Location: cart.php');
    exit;
}

// 顯示購物車
$items = $cart->display_contents($session);
?>
<table>
<tr><th>商品</th><th>單價</th><th>數量</th><th>小計</th><th>操作</th></tr>
<?php for ($i=0; $i

關鍵改進點(對比原始碼)

原始寫法問題改進
字串拼接 SQLSQL 注入風險極高PDO 預處理語句 + 參數綁定
mysql_* 函式PHP 7+ 已移除PDO / MySQLi
eval() 執行後端 JS極度危險、難維護前端 AJAX + JSON 回傳
單一 $GLOBALS['db']強耦合、難測試建構子注入 PDO 實例
Session ID 產生邏輯rand() 不夠隨機random_bytes() + uniqid()

現代化架構建議

  1. 依賴注入:class Cart { public function __construct(PDO $db, string $table) {...} }
  2. 介面契約:定義 CartInterface,方便替換實作(Redis、Session、資料庫)。
  3. 領域事件:加入商品時觸發 CartItemAdded 事件,解耦庫存扣減、優惠計算等副作用。
  4. 前端分離:API 回傳 JSON,前端 Vue/React 渲染,數量修改送 PATCH 請求。

總結

此購物車類別展示了「Session 識別 + 資料庫持久化 + 核心 CRUD」的經典模式。理解其邏輯後,應立即套用參數綁定、依賴注入、前後端分離等現代化實踐,構建安全、可維護、可擴展的電商核心模組。

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