例:四维数组添加
实现思路
1.观察MVC项目中商品后台添加商品模型的表单,类推出了一个数组:
2.针对上面的数组,可能会有空值现象,要进行适当过滤
3.首先要将商品类型信息入库,因为后续跟商品类型id有关联
4.将商品属性信息入库,此时涉及到数组的组装,以及属性值的转换
5.将商品类型对应的规格信息入库,此时也涉及到数组的组装,跟商品类型id有关
6.将商品类型对应的规格的规格值入库,此时还涉及到数组转换,关联的有:商品类型id和商品类型对应的规格id
7.整个逻辑要保证一致性和完整性,必须借助事务实现
8.由于逻辑较为复杂,特将控制器所应执行的逻辑分别拆分至Businesses和Common中做二次封装,实现代码的高度解耦
$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' => ['棉麻','涤纶','纯棉','羊毛']
]
],
];
封装business
<?php
namespace app\business;
use app\model\Attribute;
use app\model\Spec;
use app\model\SpecValue;
use app\model\Type;
use think\db\exception\DbException;
use think\Exception;
class TypeBusiness
{
protected static $typeId='';
protected static $specData=[];
/**
* 添加模型信息入库
* @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];
}
/**
* 规格信息入库保存的逻辑
* @param $data
*/
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 {
//将商品类型对应的规格入库,此时会返回规格主键id
self::$specData = (new Spec())->addSpec($spec);
}catch (DbException $exception){
throw new Exception("商品规格入库失败");
}
}
/**
* 规格值信息入库保存逻辑
* @param $data
*/
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 {
//再将商品类型对应的规格的规格值入库,此时已知:规格id(上一步),规格值,类型id(在第一步)
(new SpecValue())->addSpecValue($specValue);
}catch (DbException $exception){
throw new Exception("商品规格值入库失败");
}
}
/**
* 商品属性信息入库保存的逻辑
* @param $data
* @return \think\Collection
*/
public static function addAttr($data){
//组装商品属性的数组
$attr = [];
foreach ($data['attr'] as $key => $val) {
$attr[] = [
'attr_name' => $val['name'],
'sort'=>$val['sort'],
'type_id' => self::$typeId,
'attr_values' => implode(',',$val['value']),
];
}
try {
//再将商品属性入库,此时已知:属性名,排序,商品类型id,属性值需要implode转换
(new Attribute())->addAttr($attr);
}catch (DbException $exception){
throw new Exception("商品属性入库失败");
}
}
public static function saveTypeName($id,$typeName){
//将商品类型id进行赋值
self::$typeId=$id;
try {
$type=Type::saveTypeName($id,$typeName);
}catch (DbException $exception){
throw new Exception("商品类型名称修改");
}
}
}
在Common中封装数组处理的函数(针对商品属性和商品规格的非空处理)
//JSON
if (!function_exists('jsons')){
function jsons($code,$msg,$data){
return json([
'code'=>$code,
'msg'=>$msg,
'data'=>$data,
]);
}
}
//成功
if (!function_exists('okk')){
function okk($msg='',$data=[],$code=200){
return jsons($code,$msg,$data);
}
}
//失败
if (!function_exists('noo')){
function noo($msg='',$data=[],$code=500){
return jsons($code,$msg,$data);
}
}
// 四维数组空值处理的公共函数
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]);
}
}
}
foreach ($data[$filed] as $key => $val) {
// 判断整个规格值是否一个都没有
if (count($val['value']) == 0) {
// 直接将整个数组销毁
unset($data[$filed][$key]);
}
}
return $data;
}
}
控制器层
/**
* 添加
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//假设接收表单数据
$data = [
'type_name' => '裤子',
'attr' => [
[
'name' => '产地',
'sort' => 100,
'value' => ['进口', '国产', '定制']
], [
'name' => '包装',
'sort' => 100,
'value' => ['礼盒', '自封', '']
], [
'name' => '毛重',
'sort' => 100,
'value' => ['1KG', '2KG', '']
]
],
'spec' => [
[
'name' => '颜色',
'sort' => 100,
'value' => ['黑色', '白色', '灰色', '']
], [
'name' => '尺寸',
'sort' => 100,
'value' => ['S', 'L', 'XL']
], [
'name' => '面料',
'sort' => 100,
'value' => ['棉', '麻', '']
]
]
];
//校验数据
try {
$this->validate($data, [
'type_name|商品类型' => 'require',
'attr|商品属性' => 'array',
'spec|商品规格' => 'array',
]);
} catch (ValidateException $exception) {
return noo($exception->getMessage());
}
// 启动事务
Db::startTrans();
try {
// 调用逻辑层将模型信息入库并得到模型的主键id
$type = TypeBusiness::addType($data);
// 调用公共函数处理将规格名称数组过滤空值
$data=arrayFilter($data,"spec");
// 调用逻辑层将规格信息入库保存
TypeBusiness::addSpec($data);
// 调用逻辑层将规格值信息入库保存
TypeBusiness::addSpecValue($data);
// 调用公共函数处理将规格名称数组过滤空值
$data=arrayFilter($data,"attr");
// 调用逻辑层将属性信息入库保存
TypeBusiness::addAttr($data);
// 提交事务
Db::commit();
// 返回数据
return okk('',$type);
}catch (Exception $exception){
// 回滚事务
Db::rollback();
// 给出错误提示
return noo($exception->getMessage());
}
}
模型层
//商品类型批量添加
public static function addType($data){
return self::create($data,['type_name']);
}
//商品属性批量添加
public function addAttr($data){
return $this->saveAll($data);
}
//商品规格名称入库
public function addSpec($data){
return $this->saveAll($data);
}
//规格值批量入库
public function addSpecValue($data){
return $this->saveAll($data);
}
例:四维数组修改
定义路由
创建控制器方法
接收数据
参数检测
修改模型数据
修改规格名称(去除空的规格值,去除没有规格值的规格名,删除原规格名称,添加新规格名称)
修改规格值(删除原规格值,添加新规格值)
修改属性数据(去除空的属性值,删除原属性,添加新属性)
返回数据
代码思路:
1. 接收参数
2. 检测数据
3. 将模型名修改
4. 处理规格以及规格值
5. 将规格批量删除
6. 处理出添加规格的结果集
7. 将规格批量添加
8. 将规格值批量删除
9. 处理出添加规格值的结果集
10. 将规格值批量添加
11. 过滤属性的数据
12. 将属性的数据批量删除
13. 处理出添加属性的结果集
14. 将属性放入属性表中
15. 返回结果。提交事务或回滚事务
// 假设接收的表单数据
$data = [
'type_name' => '电脑',
'attr' => [
[
'name' => '包装',
'sort' => 100,
'value' => ['礼盒装', '', '电脑包', '纸盒', '']
],
[
'name' => '产地',
'sort' => 100,
'value' => ['北京', '韩国', '美国']
]
],
'spec' => [
[
'name' => "颜色",
'sort' => 100,
'value' => ['黑色', '灰色', '蓝色', '红色', '白色', '', '']
], [
'name' => "尺寸",
'sort' => 100,
'value' => ['13寸', '14寸', '15.6寸', '17寸', '32寸']
],
[
'name' => "配置",
'sort' => '100',
'value' => ['8核|独立显卡|高色域', '4核|双显卡', '2核|独立显卡', '没核']
],
[
'name' => "内存",
'sort' => '100',
'value' => ['4G', '8G', '16G', '32G']
]
],
];
封装business同上
在Common中封装数组处理的函数(针对商品属性和商品规格的非空处理)同上
控制器层
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
// 验证id必须为纯数字
if (!is_numeric($id) || $id == 0) {
return fail("参数格式不正确");
}
// 接收参数
$data = $request->post();
// 假设接收的表单数据
$data = [
'type_name' => '电脑',
'attr' => [
[
'name' => '包装',
'sort' => 100,
'value' => ['礼盒装', '', '电脑包', '纸盒', '']
],
[
'name' => '产地',
'sort' => 100,
'value' => ['北京', '韩国', '美国']
]
],
'spec' => [
[
'name' => "颜色",
'sort' => 100,
'value' => ['黑色', '灰色', '蓝色', '红色', '白色', '', '']
], [
'name' => "尺寸",
'sort' => 100,
'value' => ['13寸', '14寸', '15.6寸', '17寸', '32寸']
],
[
'name' => "配置",
'sort' => '100',
'value' => ['8核|独立显卡|高色域', '4核|双显卡', '2核|独立显卡', '没核']
],
[
'name' => "内存",
'sort' => '100',
'value' => ['4G', '8G', '16G', '32G']
]
],
];
// 校验参数
try {
$this->validate($data, [
'type_name|商品类型' => "require",
'attr|商品属性' => "array",
'spec|商品规格' => 'array'
]);
} catch (ValidateException $exception) {
return fail($exception->getMessage());
}
// 启动事务
Db::startTrans();
try{
// 修改商品类型名称
$type = TypesBusiness::saveTypeName($id, $data['type_name']);
// 调用公共函数处理将规格名称数组过滤空值
$data = arrayFilter($data, "spec");
// 删除规格
Spec::getTypeIdByDeleteSpec($id);
// 调用逻辑层将规格信息入库保存
TypesBusiness::addSpec($data);
// 删除规格值
SpecValue::getTypeIdByDeleteSpecValue($id);
// 调用逻辑层将规格值入库保存
TypesBusiness::addSpecValue($data);
// 调用公共函数处理将规格名称数组过滤空值
$data = arrayFilter($data, "attr");
// 删除属性值
Attribute::getTypeIdByDeleteAttr($id);
// 调用逻辑层将属性信息入库保存
TypesBusiness::addAttr($data);
// 提交事务
Db::commit();
// 返回数据
return okk('',$type);
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
// 给出错误提示
return noo($e->getMessage());
}
}
注意:此处采用暴力方式,先将数据删除,后进行新增,因为修改的逻辑比较复杂,特使用此方式,但该方式不是最优,设计到效率问题。
模型层
//修改商品类型
public static function saveTypeName($id,$type_name){
return self::update(['type_name'=>$type_name],['id'=>$id]);
}
//商品属性批量添加
public function addAttr($data){
return $this->saveAll($data);
}
//商品属性批量删除
public static function AttributeDelete($type_id){
return self::where('type_id',$type_id)->delete();
}
//商品规格名称入库
public function addSpec($data){
return $this->saveAll($data);
}
//商品规格删除
public static function SpecDelete($type_id){
return self::where('type_id',$type_id)->delete();
}
//规格值批量入库
public function addSpecValue($data){
return $this->saveAll($data);
}
//规格值批量删除
public static function specValueDel($type_id){
return self::where('type_id',$type_id)->delete();
}
|