商品規格的設計還需要考慮,當U規格更新,添加,刪除時,會對商品,購物車有什么影響。
更新規格和商品時修改了SpecGoodsPrice表。
tpshop更新規格時并沒有修改購物車,更新商品時只修改購物車spec_key等于''的數據,也就是刪除規格暫時不會影響購物車,購物車還看得到原先的舊的商品數據。
但是當下單時,由于購物車數據有spec_key,由于使用
~~~
getGoodNum($val['goods_id'], $val['spec_key']);
/**
* 獲取商品庫存
* @param type $goods_id 商品id
* @param type $key 庫存 key
*/
function getGoodNum($goods_id, $key)
{
if (!empty($key)) {
return M("SpecGoodsPrice")->where("goods_id = $goods_id and `key` = '$key'")->getField('store_count');
} else {
return M("Goods")->where("goods_id = $goods_id")->getField('store_count');
}
}
~~~
獲取商品,所以SpecGoodsPrice表中沒有,那就沒有庫存了,這個邏輯也很合理。(這種沒有庫存其實是沒有這種規格了商品了,可以檢測出來,提示用戶商品失效)
規格直接更改可以改變商品,SKU這樣有點侵入式的感覺,感覺最好是規格信息變動不會影響線上業務,需要更新商品才會變動其他信息才比較好。
實際上電商這種規格表的設計,每次更新商品,哪怕沒有信息變化,就點擊保存,都會引起SpecGoodsPrice(相當于產品表SKU表)變化,因為刪除了舊數據,重新添加一遍,這樣就導致了每次id都會變化,所以這也就是天貓商品銷量只能統計某個商品,而不能統計某個SKU了,一個商品的生命周期可能有很多SKU生命周期,這也是一款產品下面有的人買的是上面沒有的規格的原因。參考:[為什么在京東的商品詳情頁每點擊一次商品參數就要刷新一次頁面?](https://www.zhihu.com/question/27859589)
既然這個SKU id是變化了,那就不能用在業務邏輯中,可以忽略它,商品購買后訂單記錄指向的是商品的ID,SPU id,然后有一個規格組 套餐: 套餐一…… 這樣的字段,這個只是起展示作用的,沒有其他意義了。
購物車中其實也是這樣的規格信息,起展示作用。
但是tpshop的設計有一點新穎。
那就是規格用了兩張表:tb_spec和tb_spec_item
這樣就就能得到一個key(spec_key):其實就是spec_item_id
那么真的key_key…… 就能代表 一組規格了,就是spec_id:spec_name 套餐: 套餐一
>[danger] 注意:tpshop將key的排序轉變為小到大的排序,這很重要,前臺也遵循這個排序,只有這樣才能標識唯一的SKU。另外還要注意,key_name沒有根據item_key的順序,不然可能造成SPU下的不同SKU規格順序不相同。
這涉及到規格項排序問題(規格項順序就是規格的順序,如:顏色,尺碼,套餐)
而specInput的排序只是讓規格值小的放在前面,便于合并單元格好看,應該不影響任何業務邏輯。
另外規格值也要有順序,便于展示時自由調整。
所以設計到業務相關的順序應該有規格(名)排序和規格值排序。其他的都沒有排序,SKU也沒有(只是邏輯數據而已)。
tpshop的設計是:
首先為同類商品建立商品規格。可以建立多個規格,每個規格可以有多個規格項。
然后這組規格就可以被該類型的商品選用了。注意這里是選用,而不是全部非得都要用。
當選擇了多個規格的多個規格項之后,就要得出選中的規格的規格項的笛卡爾乘積,乘積的值就是該商品SKU數量,也叫做規格組數量,一組規格的商品是不可再分的完整的商品。
### 名詞解釋:
顏色:`紅色` `黃色`
尺碼: `M碼` `L碼` `XL碼`
套餐: `套餐一`
----
上面說明了,這件商品規格的信息:
該商品有**3種類型的規格**,**規格名稱**分別為:`顏色`,`尺碼`,`套餐`
其中顏色規格的規格值有:`紅色`,`黃色`
SKU就是笛卡爾乘積 T = R * S
這些規格共有六種交集。也就是說有六個SKU。SKU的數量登錄規格的笛卡爾積,并且每個SKU都是完整的規格組,規格組由最小單元規格的鍵值對所組成,規格名 : 規格值。鍵值對組成了一個規格項。
笛卡爾的每個交集都是唯一的,所以一個SPU下的SKU(規格組)也是唯一的。
一個規格組的鍵值對的數量就是剛才選中的規格種類的數量,一個SPU下的每個SKU的規格規格項數量是一樣的,規格的順序也都是一樣的,只是規格值不同。也就是說“鍵”都是一樣的,只是“值”不同而已。如果不是這樣,那就不合法。
每一個規格組都包含某個規格的某個規格項。
`顏色:紅色,尺碼:M碼,套餐:套餐一` **(規格組 SKU)**
`顏色:紅色` —— **規格項(鍵值對)**
* * * * *
### 商品規格展示(兩處)
規格展示有兩處,一處是后臺,這個要注意,不要忘記了,這兒是選擇,并不是類型下的規格都是的,也可以不選的。所以這個規格展示必須從規格表中讀出來。
第二處就是商品詳情頁的規格展示,這個是商品的全部SKU規格,也就是后臺所有選中的規格,這個規格要從SKU表中讀出來,thshop就是這么做的(糾錯,tpshop其實還是從規格表中讀出的,只不過用SKU中的數據從規格表中讀而已,所以它要特別小心它的規格排序了,它也分別在前端后端做統一轉換的了),但是iwebshop就多此一舉,在商品表里面有個字段spec_array,他把所有規格sku放在這里存一份了,商品詳情頁面展示規格就是使用的這個字段的數據。這種方式太冗余了(其實這樣也沒什么不可,適當的時候反三范式也是好方法,免得每次計算這個數據麻煩),從SKU表中很容易得到所需要的數據。拿到商品所有的SKU,然后處理下數據就可以了。
這里要注意一個問題,那就是規格(名)排序的問題,有的算法需要考慮“順序”一致的問題,請注意。
### 擴展
tpshop的笛卡爾乘積實在服務端php計算的,采用的設計思想是通過將多個數組不斷的轉換為兩個數組來進行計算,因為只有兩個數組時才可以很簡單的計算出笛卡爾乘積。
~~~
/**
* 多個數組的笛卡爾積
*
* @param unknown_type $data
*/
function combineDika()
{
$data = func_get_args();
$data = current($data);
$cnt = count($data);
$result = array();
$arr1 = array_shift($data);
foreach ($arr1 as $key => $item) {
$result[] = array($item);
}
foreach ($data as $key => $item) {
$result = combineArray($result, $item);
}
return $result;
}
/**
* 兩個數組的笛卡爾積
* @param unknown_type $arr1
* @param unknown_type $arr2
*/
function combineArray($arr1, $arr2)
{
$result = array();
foreach ($arr1 as $item1) {
foreach ($arr2 as $item2) {
$temp = $item1;
$temp[] = $item2;
$result[] = $temp;
}
}
return $result;
}
~~~
不過感覺這兩個函數沒有設計好,功能有融合,因為第二個函數的第一個參數只能是二維數組才可以。顯然這一步又在第一個函數里面做了。
### 參考:
- [笛卡爾乘積](http://baike.baidu.com/link?url=ZC7bEfQVmex1SrG5U8LMZU1MAcxfSTItoKk17H3nVv0WcbvzKgiqDNHUHxOUnc_DWsBZV5cLUOhRHbA573ikZCLuwq4PAieVKYoNXx-83YafC7K3VtST34goTIuOOL03nHkaB1s1_n1HONPQU8QWtq2xiTylvbxaxEPmVyPTCzQbtvrYh2Lk74ld62BRh_ExhAzDHnen4JDnHn6B8bfMF4EIWWbM26z8XEPuGw2XbBW)
- [js實現的笛卡爾乘積-商品發布](http://www.cnblogs.com/xumanbu/p/4552290.html)
- [js 笛卡爾積算法與多重數組笛卡爾積的例子](http://blog.csdn.net/a473554142/article/details/48970225)
- [淘寶、京東 多規格組合商品 的數據庫設計](https://segmentfault.com/q/1010000005955316)
- [非小型電子商務系統設計經驗分享](http://www.cnblogs.com/mmmjiang13/archive/2012/07/05/2575538.html)
- [再從淘寶數據結構來看電子商務中商品屬性設計](http://www.cnblogs.com/mmmjiang13/archive/2011/08/03/2125640.html)
### 其他
商品類型對應的規格和屬性,這樣的方式跟淘寶一樣,其實不一定要這樣,這很適用于相對標準化的商品,不太靈活,比如商品不能單獨隨意的添加規格和屬性,比如外賣餐品的大份,小份,這只需要一個簡單的規格就可以了,而且不是每個品類都有這樣的規格,這樣能夠隨意自定義就靈活多了。
還有需要考慮如果修改類型的規格,規格值會對給類型的商品帶來什么影響呢?這些都需要考慮的。
還有商品變動,會對用戶的購物車產生什么影響,等等要素。
- 開始
- 公益
- 更好的使用看云
- 推薦書單
- 優秀資源整理
- 技術文章寫作規范
- SublimeText - 編碼利器
- PSR-0/PSR-4命名標準
- php的多進程實驗分析
- 高級PHP
- 進程
- 信號
- 事件
- IO模型
- 同步、異步
- socket
- Swoole
- PHP擴展
- Composer
- easyswoole
- php多線程
- 守護程序
- 文件鎖
- s-socket
- aphp
- 隊列&并發
- 隊列
- 講個故事
- 如何最大效率的問題
- 訪問式的web服務(一)
- 訪問式的web服務(二)
- 請求
- 瀏覽器訪問阻塞問題
- Swoole
- 你必須理解的計算機核心概念 - 碼農翻身
- CPU阿甘 - 碼農翻身
- 異步通知,那我要怎么通知你啊?
- 實時操作系統
- 深入實時 Linux
- Redis 實現隊列
- redis與隊列
- 定時-時鐘-阻塞
- 計算機的生命
- 多進程/多線程
- 進程通信
- 拜占庭將軍問題深入探討
- JAVA CAS原理深度分析
- 隊列的思考
- 走進并發的世界
- 鎖
- 事務筆記
- 并發問題帶來的后果
- 為什么說樂觀鎖是安全的
- 內存鎖與內存事務 - 劉小兵2014
- 加鎖還是不加鎖,這是一個問題 - 碼農翻身
- 編程世界的那把鎖 - 碼農翻身
- 如何保證萬無一失
- 傳統事務與柔性事務
- 大白話搞懂什么是同步/異步/阻塞/非阻塞
- redis實現鎖
- 淺談mysql事務
- PHP異常
- php錯誤
- 文件加載
- 路由與偽靜態
- URL模式之分析
- 字符串處理
- 正則表達式
- 數組合并與+
- 文件上傳
- 常用驗證與過濾
- 記錄
- 趣圖
- foreach需要注意的問題
- Discuz!筆記
- 程序設計思維
- 抽象與具體
- 配置
- 關于如何學習的思考
- 編程思維
- 談編程
- 如何安全的修改對象
- 臨時
- 臨時筆記
- 透過問題看本質
- 程序后門
- 邊界檢查
- session
- 安全
- 王垠
- 第三方數據接口
- 驗證碼問題
- 還是少不了虛擬機
- 程序員如何談戀愛
- 程序員為什么要一直改BUG,為什么不能一次性把代碼寫好?
- 碎碎念
- 算法
- 實用代碼
- 相對私密與絕對私密
- 學習目標
- 隨記
- 編程小知識
- foo
- 落盤
- URL編碼的思考
- 字符編碼
- Elasticsearch
- TCP-IP協議
- 碎碎念2
- Grafana
- EFK、ELK
- RPC
- 依賴注入
- 科目一
- 開發筆記
- 經緯度格式轉換
- php時區問題
- 解決本地開發時調用遠程AIP跨域問題
- 后期靜態綁定
- 談tp的跳轉提示頁面
- 無限分類問題
- 生成微縮圖
- MVC名詞
- MVC架構
- 也許模塊不是唯一的答案
- 哈希算法
- 開發后臺
- 軟件設計架構
- mysql表字段設計
- 上傳表如何設計
- 二開心得
- awesomes-tables
- 安全的代碼部署
- 微信開發筆記
- 賬戶授權相關
- 小程序獲取是否關注其公眾號
- 支付相關
- 提交訂單
- 微信支付筆記
- 支付接口筆記
- 支付中心開發
- 下單與支付
- 支付流程設計
- 訂單與支付設計
- 敏感操作驗證
- 排序設計
- 代碼的運行環境
- 搜索關鍵字的顯示處理
- 接口異步更新ip信息
- 圖片處理
- 項目搭建
- 閱讀文檔的新方式
- mysql_insert_id并發問題思考
- 行鎖注意事項
- 細節注意
- 如何處理用戶的輸入
- 不可見的字符
- 抽獎
- 時間處理
- 應用開發實戰
- python 學習記錄
- Scrapy 教程
- Playwright 教程
- stealth.min.js
- Selenium 教程
- requests 教程
- pyautogui 教程
- Flask 教程
- PyInstaller 教程
- 蜘蛛
- python 文檔相似度驗證
- thinkphp5.0數據庫與模型的研究
- workerman進程管理
- workerman網絡分析
- java學習記錄
- docker
- 筆記
- kubernetes
- Kubernetes
- PaddlePaddle
- composer
- oneinstack
- 人工智能 AI
- 京東
- pc_detailpage_wareBusiness
- doc
- 電商網站設計
- iwebshop
- 商品規格分析
- 商品屬性分析
- tpshop
- 商品規格分析
- 商品屬性分析
- 電商表設計
- 設計記錄
- 優惠券
- 生成唯一訂單號
- 購物車技術
- 分類與類型
- 微信登錄與綁定
- 京東到家庫存系統架構設計
- crmeb
- 命名規范
- Nginx https配置
- 關于人工智能
- 從人的思考方式到二叉樹
- 架構
- 今日有感
- 文章保存
- 安全背后: 瀏覽器是如何校驗證書的
- 避不開的分布式事務
- devops自動化運維、部署、測試的最后一公里 —— ApiFox 云時代的接口管理工具
- 找到自己今生要做的事
- 自動化生活
- 開源與漿果
- Apifox: API 接口自動化測試指南