laravel电商学习系列-05 购物车&订单模块

1. 前言

购物车是电商必不可少的功能,课程中电商系统把商品下单的唯一入口放在了购物车商品列表,也就是说只能在购物车商品列表页面选择商品下单购买。课程传送门
本模块功能包括:

  • 购物车
  • 订单

2. 功能分析

2.1 购物车

2.1.1 需求分析

  • 用户可以将商品SKU添加到购物车、从购物车移除删除商品SKU;
  • 用户可以修改自己购物车中商品的数量;
  • 下架的商品只能够移除,不能够修改或勾选下单;

附功能效果图如下:


商品加入购物车-效果图

2.1.2 表设计

  • 实现逻辑
    购物车是用户属性,存放的是商品SKU的合集,处理逻辑很简单,就是普通的增删改查。在显示的时候需要显示商品的详细信息,需要做一些例如库存、商品状态的简单判断。
  • 表设计
    用户可以在购物车列表页面直接选择商品下单购买,所以购物车中存放的商品信息需包含下单所需的详细商品数据,包括具体的商品SKU、数量;
    具体表结构如下:
CREATE TABLE `cart_items` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT, # 自增ID
  `user_id` int(10) unsigned NOT NULL, # 所属用户ID
  `product_sku_id` int(10) unsigned NOT NULL, # 选择的商品SKU
  `amount` int(10) unsigned NOT NULL, # 商品数量
  PRIMARY KEY (`id`),
  KEY `cart_items_user_id_foreign` (`user_id`),
  KEY `cart_items_product_sku_id_foreign` (`product_sku_id`),
  CONSTRAINT `cart_items_product_sku_id_foreign` FOREIGN KEY (`product_sku_id`) REFERENCES `product_skus` (`id`) ON DELETE CASCADE,
  CONSTRAINT `cart_items_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

课程中也有提到,表名和字段名最好能做到见名思意,过个一年半载,看到表名/字段名就能想起它的含义。这里购物车的表名是cart_items,准确地说,我们建的不是购物车表,一个用户一个购物车,一个购物车可以存放多样商品,我们建的是购物车商品表,就像前面的商品收藏一样,只是在这里,我们形象地理解这些待买的商品的合集叫做购物车,因此表名cart_items是购物车中商品项的意思。

2.1.3 代码借鉴

课程中,购物车是登录之后才能操作,直接用数据库存储,实现比较简单。可以思考拓展一下用户在登录/非登录状态下购物车数据怎么存放,多端购物车数据怎么同步?
可以参考以下思路:
大型电商项目购物车的实现
购物车实现及原理(仿京东实现原理)

2.2 订单

订单是电商系统必不可少的一环。与之相关的有商品模块、支付模块、物流模块,不同商品种类,不同支付方式,不同物流公司的处理方式都不一样,因此在编码设计和表设计上需要考虑清楚。

2.2.1 需求分析

  • 支持多项商品合并成一个订单支付;
  • 自动关闭超时未支付订单;
  • 一个订单中的多个商品可以分开评分;
  • 一个订单中的商品时合并发货,物流信息统一;
  • 购买完成后,需将购买商品从购物车中删除;
购物车下单界面-效果图

2.2.2表设计

  • 实现逻辑
    订单由用户触发创建,不能人为修改,应依据客观事实由程序更新,属于用户操作数据不能被人为删除。
    整个的订单生命周期如下:


    订单生命周期-流程图

    每一个阶段都需要维护订单相应信息:

    • 创建订单,此时只更新用户信息、收件地址信息、商品信息,订单状态、物流信息、支付信息只初始化(默认值);
    • 支付完成/失败,更新支付信息;
    • 商品发货,更新物流信息;
    • 用户收货/退货,更新物流信息、支付退款信息、订单状态;
  • 表设计
    因为一个订单可以包含多项商品,因此采用order 订单表order_item 订单子项表分别保存订单信息和订单商品项信息;order 订单表用于存储订单整体属性,包括支付信息,物流信息,收件信息等;order_item 订单子项表存储购买的商品 SKU 信息,包括商品 SKU ,对 SKU 的评分等;其中,在order 订单表保存了收件人的地址快照而不用户收货地址 ID ,是因为订单具有时效性,而用户收获地址是可以修改的;在order_item 订单子项表存储 product_id 商品 ID 字段,这是个冗余字段,它可以通过 product_sku_id 查询,但有时候增加冗余字段可以减少查询,提高查询效率。

# 订单表
CREATE TABLE `orders` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT, # 自增ID
  `no` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, # 订单号
  `user_id` int(10) unsigned NOT NULL, # 所属用户ID
  `address` text COLLATE utf8mb4_unicode_ci NOT NULL, # 地址快照
  `total_amount` decimal(10,2) NOT NULL, # 订单总金额
  `remark` text COLLATE utf8mb4_unicode_ci, #备注
  `paid_at` datetime DEFAULT NULL, # 支付时间
  `payment_method` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, # 支付方式
  `payment_no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, # 第三方支付单号
  `refund_status` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'pending', # 退款状态
  `refund_no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, # 第三方退款单号
  `closed` tinyint(1) NOT NULL DEFAULT '0', # 订单是否关闭
  `reviewed` tinyint(1) NOT NULL DEFAULT '0', # 订单是否评价
  `ship_status` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'pending', # 物流状态
  `ship_data` text COLLATE utf8mb4_unicode_ci, # 物流信息
  `extra` text COLLATE utf8mb4_unicode_ci, # 其他数据
  `created_at` timestamp NULL DEFAULT NULL, # 订单创建时间
  `updated_at` timestamp NULL DEFAULT NULL, # 订单更新时间
  PRIMARY KEY (`id`),
  UNIQUE KEY `orders_no_unique` (`no`),
  UNIQUE KEY `orders_refund_no_unique` (`refund_no`),
  KEY `orders_user_id_foreign` (`user_id`),
  KEY `orders_coupon_code_id_foreign` (`coupon_code_id`),
  CONSTRAINT `orders_coupon_code_id_foreign` FOREIGN KEY (`coupon_code_id`) REFERENCES `coupon_codes` (`id`) ON DELETE SET NULL,
  CONSTRAINT `orders_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

# 订单子项表
CREATE TABLE `order_items` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT, # 自增ID
  `order_id` int(10) unsigned NOT NULL, # 所属订单ID
  `product_id` int(10) unsigned NOT NULL, # 商品ID
  `product_sku_id` int(10) unsigned NOT NULL, # 所选商品SKU
  `amount` int(10) unsigned NOT NULL, # 数量
  `price` decimal(10,2) NOT NULL, # 价额
  `rating` int(10) unsigned DEFAULT NULL, # 评分
  `review` text COLLATE utf8mb4_unicode_ci, # 评价
  `reviewed_at` timestamp NULL DEFAULT NULL, # 评价时间
  PRIMARY KEY (`id`),
  KEY `order_items_order_id_foreign` (`order_id`),
  KEY `order_items_product_id_foreign` (`product_id`),
  KEY `order_items_product_sku_id_foreign` (`product_sku_id`),
  CONSTRAINT `order_items_order_id_foreign` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`) ON DELETE CASCADE,
  CONSTRAINT `order_items_product_id_foreign` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON DELETE CASCADE,
  CONSTRAINT `order_items_product_sku_id_foreign` FOREIGN KEY (`product_sku_id`) REFERENCES `product_skus` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=188 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

2.2.3 代码借鉴

订单这一块的代码质量很高,值得反复推敲。包括:

  • service的使用,代码封装提供代码复用性;
  • 订单流水号的创建方法,加上循环增加代码的健壮性;
  • 延迟队列的使用姿势很巧妙;
  • 事件监听器;

上一节: 04 商品模块-进阶 众筹
下一节:06 支付模块

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容