商城后台系统商品模型(类型)新增接口开发

商品模型新增

接口文档

请求地址

POST /types

需进行token认证

示例: http://adminapi.tbyue.com/types

请求参数

名称类型必填备注
type_namestring模型名
specint规格数组
attrint属性数组

参数示例:

type_name: 手机
spec[0][name]: 颜色
spec[0][sort]: 50
spec[0][value][]: 白色
spec[0][value][]: 黑色
spec[1][name]: 内存
spec[1][sort]: 50
spec[1][value][]: 64G
spec[1][value][]: 128G
attr[0][name]: 毛重
attr[0][sort]: 50
attr[0][value][]: 
attr[1][name]: 产地
attr[1][sort]: 50
attr[1][value][]: 进口
attr[1][value][]: 国产

返回数据

名称备注
id模型id
type_name模型名

返回示例

{
    "id": 16,
    "type_name": "手机"
}

实现思路

1.观察MVC项目中商品后台添加商品模型的表单,类推出了一个数组:

$data = [
    'type_name' => '西裤',
    'attr' => [
        [
            'name' => '毛重',
            'sort' => 100,
            'value' => ['500g', '', '2000g', '5000g', '']
        ],
        [
            'name' => '产地',
            'sort' => 100,
            'value' => ['国产', '港货', '美版']
        ]
    ],
    'spec' => [
        [
            'name' => "颜色",
            'sort' => 100,
            'value' => ['黑色', '灰色', '蓝色', '红色', '白色', '', '']
        ], [
            'name' => "尺码",
            'sort' => 100,
            'value' => ['S', 'L', 'M', 'XL', 'XXL', "XXXL"]
        ],
        [
            'name' => "面料",
            'sort' => '100',
            'value' => ['棉麻','涤纶','纯棉','羊毛']
        ]
    ],
];

2.针对上面的数组,可能会有空值现象,要进行适当过滤

3.首先要将商品类型信息入库,因为后续跟商品类型id有关联

4.将商品属性信息入库,此时涉及到数组的组装,以及属性值的转换

5.将商品类型对应的规格信息入库,此时也涉及到数组的组装,跟商品类型id有关

6.将商品类型对应的规格的规格值入库,此时还涉及到数组转换,关联的有:商品类型id和商品类型对应的规格id

7.整个逻辑要保证一致性和完整性,必须借助事务实现

8.由于逻辑较为复杂,特将控制器所应执行的逻辑分别拆分至Businesses和Common中做二次封装,实现代码的高度解耦

在商品的类型模型中定义添加方法

/**
 * 商品类型入库
 * @param $data
 * @return Type|Model
 */
public static function addType($data){
    return self::create($data,['type_name']);
}

在控制器层调用逻辑层进行添加

// 调用逻辑层将模型信息入库并得到模型的主键id
$type = TypesBusiness::addType($data);

逻辑层执行商品模型添加

/**
 * 添加模型信息入库
 * @param $data
 */
public static function addType($data)
{
    try {
        // 先将商品类型名称入库,此时能获得到主键id
        $type = Type::addType($data);
    } catch (DbException $exception) {
        throw new Exception("商品类型入库失败");
    }
    self::$typeId = $type->id;
    // 返回新增的商品模型
    return ['type_id'=>$type->id,'type_name'=>$type->type_name];
}

思考:此处为何使用self将id保存起来呢?

在Common中封装数组处理的函数(针对商品属性和商品规格的非空处理)

// 四维数组空值处理的公共函数
if(!function_exists("arrayFilter")){
    function arrayFilter($data,$filed){
        // 过滤数组中的空元素
        foreach ($data[$filed] as $key => $val) {
            // 判断规格名称|属性名称是否填写
            if (trim($val['name']) == "") {
                // 直接将整个数组销毁
                unset($data[$filed][$key]);
            }
            // 循环处理规格值
            foreach ($val['value'] as $k => $v) {
                // 判断规格值是否填写
                if (trim($v) == "") {
                    unset($data[$filed][$key]['value'][$k]);
                }
            }
            // 判断整个规格值是否一个都没有
            if (count($val['value']) == 0) {
                // 直接将整个数组销毁
                unset($data[$filed][$key]);
            }
        }
        return $data;
    }
}

思考:为何将数组处理的方法放置在common中呢?

在控制器层调用公共函数处理将规格名称数组过滤空值

$data = arrayFilter($data, "spec");

调用逻辑层将规格信息入库保存

TypesBusiness::addSpec($data);

规格信息入库前处理逻辑

/**
* 规格信息入库保存的逻辑
* @param $data
* @return \think\Collection
* @throws \Exception\
*/
public static function addSpec($data)
{
    // 组装spec表所需数据
    $spec = [];
    foreach ($data['spec'] as $val) {
        $spec[] = [
            'type_id' => self::$typeId,
            'spec_name' => $val['name'],
            'sort' => $val['sort']
        ];
    }
    try {
        // 将商品类型对应的规格入库保存
        self::$specData = (new Spec())->addSpec($spec);
    } catch (DbException $exception) {
        throw new Exception("商品规格入库失败");
    }
}

规格模型层

/**
 * 商品规格名称入库
 * @param $data
 * @return \think\Collection
 * @throws \Exception
 */
public function addSpec($data){
    return $this->saveAll($data);
}

调用逻辑层将规格值信息入库保存

TypesBusiness::addSpecValue($data);

规格值信息入库前处理逻辑

/**
 * 规格值信息入库保存的逻辑
 * @param $data
 * @param $specData
 * @throws \Exception
 */
public static function addSpecValue($data)
{
    // 取出specValue的值
    foreach ($data['spec'] as $key => $val) {
        foreach ($val['value'] as $k => $v) {
            $specValue[] = [
                'spec_value' => $v,
                'type_id' => self::$typeId,
                'spec_id' => self::$specData[$key]['id']
            ];
        }
    }
    try {
        // 将规格值入库保存
        (new SpecValue())->addSpecValue($specValue);
    } catch (DbException $exception) {
        throw new Exception("商品规格值入库失败");
    }
}

规格值模型

/**
 * 规格值批量入库
 * @param $data
 * @return \think\Collection
 * @throws \Exception
 */
public function addSpecValue($data){
    return $this->saveAll($data);
}

调用公共函数处理将属性名称数组过滤空值

$data = arrayFilter($data, "attr");

调用逻辑层将属性信息入库保存

TypesBusiness::addAttr($data);

属性信息入库前处理逻辑

/**
 * 属性信息入库保存的逻辑
 * @param $data
 * @return \think\Collection
 * @throws \Exception
 */
public static function addAttr($data)
{
    // 组装商品属性的数组
    $attr = [];
    foreach ($data['attr'] as $key => $val) {
        $attr[] = [
            'attr_name' => $val['name'],
            'type_id' => self::$typeId,
            'attr_values' => implode(",", $val['value'])
        ];
    }
    try {
        // 将商品属性入库保存
        (new Attribute())->addAttr($attr);
    } catch (DbException $exception) {
        throw new Exception("商品属性入库失败");
    }
}

属性模型

/**
 * 商品属性批量添加
 * @param $data
 * @return \think\Collection
 * @throws \Exception
 */
public function addAttr($data){
    return $this->saveAll($data);
}

上面的操作都要基于:异常处理和事务处理,逻辑缜密

整体控制器层代码

/**
* 商品模型新增
* @param Request $request
* @return Json
*/
public function save(Request $request)
{
    // 假设接收的表单数据
    $data = [
        'type_name' => '西裤',
        'attr' => [
            [
                'name' => '毛重',
                'sort' => 100,
                'value' => ['500g', '', '2000g', '5000g', '']
            ],
            [
                'name' => '产地',
                'sort' => 100,
                'value' => ['国产', '港货', '美版']
            ]
        ],
        'spec' => [
            [
                'name' => "颜色",
                'sort' => 100,
                'value' => ['黑色', '灰色', '蓝色', '红色', '白色', '', '']
            ], [
                'name' => "尺码",
                'sort' => 100,
                'value' => ['S', 'L', 'M', 'XL', 'XXL', "XXXL"]
            ],
            [
                'name' => "面料",
                'sort' => '100',
                'value' => ['棉麻','涤纶','纯棉','羊毛']
            ]
        ],
    ];
    // 校验数据
    try {
        $this->validate($data, [
            'type_name|商品类型' => "require",
            'attr|商品属性' => "array",
            'spec|商品规格' => 'array'
        ]);
    } catch (ValidateException $exception) {
        return fail($exception->getMessage());
    }
    // 启动事务
    Db::startTrans();
    try {
        // 调用逻辑层将模型信息入库并得到模型的主键id
        $type = TypesBusiness::addType($data);
        // 调用公共函数处理将规格名称数组过滤空值
        $data = arrayFilter($data, "spec");
        // 调用逻辑层将规格信息入库保存
        TypesBusiness::addSpec($data);
        // 调用逻辑层将规格值信息入库保存
        TypesBusiness::addSpecValue($data);
        // 调用公共函数处理将规格名称数组过滤空值
        $data = arrayFilter($data, "attr");
        // 调用逻辑层将属性信息入库保存
        TypesBusiness::addAttr($data);
        // 提交事务
        Db::commit();
        // 返回数据
        return success($type);
    } catch (\Exception $e) {
        // 回滚事务
        Db::rollback();
        // 给出错误提示
        return fail($e->getMessage());
    }
}

postman测试时该功能表单参考:

<!--参考html表单-->
<form>
    <label>模型名:</label>
    <input type="text" name="type_name" value="">
    <label>规格:</label>
    <input type="text" name="spec[0][name]" value="">
    <input type="text" name="spec[0][sort]" value="">
    <input type="text" name="spec[0][vlaue][]" value="">
    <input type="text" name="spec[0][value][]" value="">
    <input type="text" name="spec[0][value][]" value="">
    <input type="text" name="spec[1][name]" value="">
    <input type="text" name="spec[1][sort]" value="">
    <input type="text" name="spec[1][value][]" value="">
    <input type="text" name="spec[1][value][]" value="">
    <input type="text" name="spec[1][value][]" value="">
    <label>属性:</label>
    <input type="text" name="attr[0][name]" value="">
    <input type="text" name="attr[0][sort]" value="">
    <input type="text" name="attr[0][value][]" value="">
    <input type="text" name="attr[1][name]" value="">
    <input type="text" name="attr[1][sort]" value="">
    <input type="text" name="attr[1][vlaue][]" value="">
    <input type="text" name="attr[1][value][]" value="">
</form>

参考数组格式:

//参数数组参考:
$params = [
    'type_name' => '手机',
    'spec' => [
        ['name' => '颜色', 'sort' => 50, 'value'=>['黑色', '白色', '金色']],
        ['name' => '内存', 'sort' => 50, 'value'=>['64G', '128G', '256G']],
    ],
    'attr' => [
        ['name' => '毛重', 'sort'=>50, 'value' => []],
        ['name' => '产地', 'sort'=>50, 'value' => ['进口', '国产']],
    ]
]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呀哈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值