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

PHP JSON 處理用戶多店鋪積分邏輯:代碼重構與最佳實踐

     編輯:PHP 相關知識

業務場景

會員在不同網咖/店鋪消費累積積分,需將各店鋪積分分別記錄於單一 JSON 欄位 integrallog 中。結構如下:

[
    {"store_id": 1, "jifen": 15},
    {"store_id": 3, "jifen": 8}
]

原始代碼問題分析

  • 函數重複定義、邏輯混雜、變數命名不清($yanzhen、$arrstore)。
  • 陣列操作錯誤:$yanzhen[$key]['store_id'] = $key 會破壞原有結構。
  • 缺乏輸入驗證($store_id 來源不明)、直接依賴 $_SESSION 難以測試。
  • 資料庫操作耦合具體 Model 寫法(m('integral')),不利單元測試。

重構版代碼 (PHP 7.4+)

<?php
declare(strict_types=1);

class IntegralService
{
    private $model;
    private $userId;

    public function __construct($model, int $userId)
    {
        $this->model = $model;
        $this->userId = $userId;
    }

    /**
     * 增加指定店鋪積分
     * @param int $storeId 店鋪 ID
     * @param int $points  增加點數(預設 5)
     * @return bool
     */
    public function addPoints(int $storeId, int $points = 5): bool
    {
        $record = $this->model->get(['user_id' => $this->userId]);
        $logs = $record ? json_decode($record['integrallog'], true) : [];

        // 正規化為 store_id => jifen 關聯陣列,方便查找
        $map = [];
        foreach ($logs as $log) {
            if (isset($log['store_id'], $log['jifen'])) {
                $map[(int)$log['store_id']] = (int)$log['jifen'];
            }
        }

        if (isset($map[$storeId])) {
            $map[$storeId] += $points;
        } else {
            $map[$storeId] = $points; // 新店鋪初始積分
        }

        // 轉回索引陣列格式存儲
        $newLogs = [];
        foreach ($map as $sid => $jf) {
            $newLogs[] = ['store_id' => $sid, 'jifen' => $jf];
        }

        $data = ['integrallog' => json_encode($newLogs, JSON_UNESCAPED_UNICODE)];

        if ($record) {
            return $this->model->edit($record['id'], $data);
        } else {
            $data['user_id'] = $this->userId;
            return $this->model->add($data);
        }
    }
}

// 使用範例(控制器中)
// $service = new IntegralService(M('integral'), $_SESSION['user_info']['user_id']);
// $service->addPoints((int)$store_id);

關鍵改進點

  1. 單一職責:邏輯封裝於 Service 類別,控制器僅負責調用。
  2. 型別宣告:嚴格模式 + 參數/回傳型別,減少隱性轉換錯誤。
  3. 資料結構正規化:以關聯陣列暫存,避免巢狀迴圈與索引錯亂。
  4. 依賴注入:Model 透過建構子傳入,便於 Mock 測試。
  5. JSON 選項:JSON_UNESCAPED_UNICODE 保留中文可讀性。

資料庫擴充建議

若積分查詢/統計頻繁,建議拆分為獨立資料表 user_integral_log (user_id, store_id, points, created_at),並建立複合索引,效能與擴展性遠優於 JSON 欄位。

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