1. 功能描述

  1. 实现类似联表的商品顺序,支持操作:

    1. 往顺序尾部添加一个商品
    2. 取商品往头部添加
    3. 取商品往尾部添加
    4. 删除任意商品

      2. 开发

      2.1 背景

      2.2 思路

      方案1:构建一个链表

      方案2:数据库级联设计

      优势:先后顺序硬关联,有明确的先后
      劣势:需要数据库花费额外的资源来维护这个关系,当出现并发的情况时,就gg,可能破坏这个硬关联,没了先后,导致这个先后链被截断

      方案3:数据库增加排序字段

      优势:通过 order by 排序,先后顺序也时明确的
      劣势:出现并发问题时,可能有会出现顺序先后同样为3,4,5的,而 order by 时,先后关系可能无法预料(注:可以与业务方确定再 order by 时增加主键id来明确先后关系)

      2.3 落地开发

      方案2:

      1. CREATE TABLE `commodity_promote_goods_sequence` (
      2. `goods_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '商品id',
      3. `pre_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '前驱id'
      4. UNIQUE KEY `goods_id` (`goods_id`)
      5. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品顺序';
      1. <?
      2. class GoodsList
      3. {
      4. /**
      5. * 获取商品顺序
      6. * @return array
      7. */
      8. public function goodsSort()
      9. {
      10. $sorted = [];
      11. $indexBy = 'pre_id';
      12. // 读取表内所有数据
      13. $dao = new CommodityPromoteGoodsSequenceDao();
      14. $list = $dao->listGoodsInfo($indexBy);
      15. if (!$list) {
      16. return [];
      17. }
      18. $sorted[$list[0]['goods_id']] = $list[0];
      19. while (count($sorted) < count($list)) {
      20. $value = $list[end($sorted)['goods_id']];
      21. $key = $value['goods_id'];
      22. if (count($sorted) == 1) {
      23. $sorted[$list[0]['goods_id']]['back_id'] = $key;
      24. }
      25. $sorted[$key] = $value;
      26. $sorted[$key]['back_id'] = $list[$key]['goods_id'] ?? '';
      27. }
      28. // 整合数据
      29. foreach ($sorted as $k => $item) {
      30. // 商品顺序后一个商品id
      31. $sorted[$k]['back_id'] = $item['back_id'] ?? '';
      32. }
      33. return $sorted;
      34. }
      35. /**
      36. * 修改商品顺序
      37. * @param int $goodsId
      38. * @param int $to
      39. * @return bool
      40. * @throws Exception
      41. */
      42. public function modifyGoodsSort($goodsId, $to)
      43. {
      44. if (!$goodsId) {
      45. return true;
      46. }
      47. $delGoodsIds = $updateSort = [];
      48. switch ($to) {
      49. case self::$goodsTo['top'] :
      50. if ($this->allGoodsList[$goodsId]['pre_id'] == 0) {
      51. break;
      52. }
      53. // 1. 置顶
      54. $updateSort[] = [
      55. 'goods_id' => $goodsId,
      56. 'pre_id' => 0,
      57. ];
      58. // 2. 接中间
      59. if (!empty($this->allGoodsList[$goodsId]['back_id'])) {
      60. $tmpGoods = $this->allGoodsList[$goodsId]['back_id'];
      61. $tmpPreId = $this->allGoodsList[$goodsId]['pre_id'];
      62. $updateSort[] = [
      63. 'goods_id' => $tmpGoods,
      64. 'pre_id' => $tmpPreId,
      65. ];
      66. }
      67. // 3. 改第二元素
      68. $rawFirstGoodsId = reset($this->allGoodsList)['goods_id'];
      69. $updateSort[] = [
      70. 'goods_id' => $rawFirstGoodsId,
      71. 'pre_id' => $goodsId,
      72. ];
      73. break;
      74. case self::$goodsTo['tail'] :
      75. (end($this->allGoodsList)['goods_id'] != $goodsId) && $updateSort[] = [
      76. 'goods_id' => $goodsId,
      77. 'pre_id' => end($this->allGoodsList)['goods_id'],
      78. ];
      79. (!empty($this->allGoodsList[$goodsId]['back_id'])) && $updateSort[] = [
      80. 'goods_id' => $this->allGoodsList[$goodsId]['back_id'],
      81. 'pre_id' => $this->allGoodsList[$goodsId]['pre_id'],
      82. ];
      83. break;
      84. case self::$goodsTo['del'] :
      85. $delGoodsIds = [$goodsId];
      86. (!empty($this->allGoodsList[$goodsId]['back_id'])) && $updateSort[] = [
      87. 'goods_id' => $this->allGoodsList[$goodsId]['back_id'],
      88. 'pre_id' => $this->allGoodsList[$goodsId]['pre_id'],
      89. ];
      90. break;
      91. }
      92. if (!$updateSort && !$delGoodsIds) {
      93. return true;
      94. }
      95. $ok = true;
      96. $delGoodsIds && $ok = CommodityPromoteGoodsSequenceDao::getInstance()->delByGoodsIds($delGoodsIds);
      97. if (!$ok) {
      98. return false;
      99. }
      100. $updateSort && $ok = CommodityPromoteGoodsSequenceDao::getInstance()->batchUpdateByGoodsId($updateSort);
      101. if (!$ok) {
      102. return false;
      103. }
      104. // 更新商品表
      105. $this->allGoodsList = $this->goodsSort();
      106. return true;
      107. }
      108. }

      方案3:

      CREATE TABLE `commodity_promote_goods_sequence` (
      `goods_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '商品id',
      `sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序',
      UNIQUE KEY `goods_id` (`goods_id`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品顺序';