分类导航数据杂谈

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_29673403/article/details/72476804

对于一个电商类网站,首页分类导航尤其重要,哪些是一级大分类,底下都有哪些小分类。别以为这些只是产品经理和市场的事情,这可大大的关乎了咱们这些程序员的工作量;你要知道在他们的文档里只需要改几个字,很简单;但是只要涉及到结构变动,甚至一个删除,对后台数据而言都是巨大的工作量,一个分类后面牵连着许许多多与它相关的店铺,商品,以及其他数据,这些都需要变更,否则就会出现孤岛数据,找不到与之牵连的分类。所以修改分类数据表都是其次,还需要对与之牵连的数据进行校验替换,让它和新的分类对应,保证数据的正常运行。所以好的分类表和一个实用的分类管理功能都是能大大节省开发时间,让我们能忙里偷闲喝杯下午茶~话不多说,作为一个被要求三期都要大改首页分类导航的苦逼程序媛,在与产品经理斗智斗勇中写了一些浅薄的管理分类好节省时间的分类相关代码,拿出来跟大家一起共勉,互相交流。

首先,上的是将从分类表中读取出来的分类数据处理成可供前台轻易显示层次结构的N维数组(项目中只到三级,但是为了代码具有可拓展性,所以,我并没有把维度写死,让方法可以自适应未来可能出现的4,5级等分类,当然我觉得这样复杂的结构并不是很好,不过,谁让我只是个程序媛,这些产品设计问题还是产品经理说了算的~),即获取分类数组。
方法一:(自适应n维)

private function initCatalog(){
        $catalogTable = InfoClass::model()->tableName();
        $nameTable = InfoClassName::model()->tableName();
        $allCatalogs = Yii::app()->db->createCommand()->select('info.gc_id, name.gc_name, info.gc_parent_id, info.gc_name_id')
        ->from($catalogTable." as info")
        ->leftJoin($nameTable." as name", "info.gc_name_id=name.gc_name_id")
        ->order("gc_sort desc, gc_id asc")
        ->queryAll();
        $topCatalog = array();
        $info = array();
        foreach($allCatalogs as $k => $value){
            $hasChildren = false;
            if(!array_key_exists($value['gc_id'],$info)){
                $info[$value['gc_id']] = array();
                $info[$value['gc_id']]['xiaji'] = array();
                $info[$value['gc_id']]['hasThird'] = false;
            }else
                $hasChildren = true;
            $info [$value ['gc_id']] ['id'] = $value ['gc_id'];
            $info [$value ['gc_id']] ['name'] = $value ['gc_name'];
            $info [$value ['gc_id']] ['gc_id'] = $value ['gc_id'];
            $info [$value ['gc_id']] ['gc_name'] = $value ['gc_name'];
            $info [$value ['gc_id']] ['gc_parent_id'] = $value ['gc_parent_id'];

            if (empty ( $value ['gc_parent_id'] )) { // 一级分类{
                $topCatalog [] = &$info [$value ['gc_id']];
            } else {
                if (! array_key_exists ( $value ['gc_parent_id'], $info )) {
                    $info [$value ['gc_parent_id']] = array ();
                    $info [$value ['gc_parent_id']] ['xiaji'] = array ();
                    $info [$value ['gc_parent_id']] ['xiaji'] [] = &$info [$value ['gc_id']];
                } else {
                    $info [$value ['gc_parent_id']] ['xiaji'] [] = &$info [$value ['gc_id']];
                    if(isset($info [$value ['gc_parent_id']] ['gc_parent_id'])){//判断父类是否已经出现,父亲出现的时候才为true
                        $grandId = $info [$value ['gc_parent_id']] ['gc_parent_id'];
                        if (array_key_exists ( $grandId, $info ))
                            $info [$grandId] ['hasThird'] = true;
                    }
                }
                if(isset($info [$value ['gc_parent_id']]) &&(!isset($info[$value ['gc_parent_id']] ['hasThird']) || (isset($info[$value ['gc_parent_id']] ['hasThird']) && !$info[$value ['gc_parent_id']] ['hasThird'])))
                    $info [$value ['gc_parent_id']] ['hasThird'] = $hasChildren;//标志它有没有孙子分类
            }
        }
        $this->allCatalogsInfo = $info;
        $this->allCatalogs = $topCatalog;
    }

看完这段代码,细心地童鞋就会发现这个代码还可适用于乱序插入数据的分类数据表(即子类或孙子类出现在父类之前的情况),其中我加了一个hasThird这个标志来判断这个分类有没有孙子类,别问我为什么,因为前台要根据有没有孙子类来显示不同的视觉效果,所以,需求决定功能(同理,可以你们也可以添加其他便于判断的标志变量来符合自己的需求要求)。
方法二(通过参数来决定生成几维,,这里举例为3维)

/**
     * 取分类列表,最多为三级
     *
     * @param int $show_deep 显示深度
     * @param array $condition 检索条件
     * @return array 数组类型的返回结果
     */
    public function getTreeClassList($show_deep='3',$condition=array()){
        $class_list = $this->getClassList($condition);
        $goods_class = array();//分类数组
        if(is_array($class_list) && !empty($class_list)) {
            $show_deep = intval($show_deep);
            if ($show_deep == 1){//只显示第一级时用循环给分类加上深度deep号码
                foreach ($class_list as $val) {
                    if($val['gc_parent_id'] == 0) {
                        $val['deep'] = 1;
                        $goods_class[] = $val;
                    } else {
                        break;//父类编号不为0时退出循环
                    }
                }
            } else {//显示第二和三级时用递归
                $goods_class = $this->_getTreeClassList($show_deep,$class_list);
            }
        }
        return $goods_class;
    }

    /**
     * 递归 整理分类
     *
     * @param int $show_deep 显示深度
     * @param array $class_list 类别内容集合
     * @param int $deep 深度
     * @param int $parent_id 父类编号
     * @param int $i 上次循环编号
     * @return array $show_class 返回数组形式的查询结果
     */
    private function _getTreeClassList($show_deep,$class_list,$deep=1,$parent_id=0,$i=0){
        static $show_class = array();//树状的平行数组
        if(is_array($class_list) && !empty($class_list)) {
            $size = count($class_list);
            if($i == 0) $show_class = array();//从0开始时清空数组,防止多次调用后出现重复
            for ($i;$i < $size;$i++) {//$i为上次循环到的分类编号,避免重新从第一条开始
                $val = $class_list[$i];
                $gc_id = $val['gc_id'];
                $gc_parent_id	= $val['gc_parent_id'];
                if($gc_parent_id == $parent_id) {
                    $val['deep'] = $deep;
                    $show_class[] = $val;
                    if($deep < $show_deep && $deep < 3) {//本次深度小于显示深度时执行,避免取出的数据无用
                        $this->_getTreeClassList($show_deep,$class_list,$deep+1,$gc_id,$i+1);
                    }
                }
                if($gc_parent_id > $parent_id) break;//当前分类的父编号大于本次递归的时退出循环
            }
        }
        return $show_class;
    }

public function getClassArray(){
    $tmp_list = $this->getTreeClassList(3);
        if (is_array($tmp_list)){
            foreach ($tmp_list as $k => $v){
                if ($v['gc_parent_id'] == $parent_id){
                    //判断是否有子类
                    if ($tmp_list[$k+1]['deep'] > $v['deep']) {
                        $v['have_child'] = 1;
                    }

                    foreach($class_name_list as $value){

                        if($v['gc_name_id']==$value['gc_name_id']){
                            $v['gc_name']=$value['gc_name'];
                        }
                    }
                    $class_list[] = $v;
                }
            }
        }
}

到此,我所用的两种获取分类数组的方法就介绍完了。那么我们来看一下分类管理功能的代码吧。(需要注意的是,我这里使用的框架是半自制框架,前身是开源时候的shopnc框架,所以,不要直接套用哦,可能会出问题的,请进行相应修改后再使用。$lang[]这个里面就是我封装了的用于显示的提示字符串,直接用字符串替换即可)
1。前台显示JS

<?php defined('InShopNC') or exit('Access Invalid!');?>
<style>
.hide{
display:none;
}
</style>
<div class="page">
  <div class="fixed-bar">
    <div class="item-title">
      <h3><?php echo $lang['goods_class_import_data'];?></h3>
      <?php echo $output['top_link'];?>
    </div>
  </div>
  <div class="fixed-empty"></div>
  <form method="post" enctype="multipart/form-data" name="form1" onsubmit="return submit();" id="form1">
    <input type="hidden" name="form_submit" value="ok" />
    <input type="hidden" name="charset" value="gbk" />
    <table class="table tb-type2">
      <tbody>
      <tr class="noborder">
          <td class="required">
          <label><?php echo $lang['goods_class_import_choose_type'];?>:</label>
          <select name="type" id="type" class="">
          <option value=""><?php echo $lang['nc_please_choose'];?>...</option>
          <option value="0">新增分类</option>
          <option value="1">分类替换</option>
          <option value="2">数据修改</option>
           <option value="3">更新deep</option>
          </select></td>
          <td class="required"><label style="color: red;" class="type_tip"></label></td>
        </tr>
        <tr class="noborder tablename hide">
          <td class="required">
          <label style="line-height: 45px"><?php echo $lang['goods_class_import_choose_table'];?>:</label>
          <select name="tablename" id="tablename">
          <option value=""><?php echo $lang['nc_please_choose'];?>...</option>
          <?php foreach ($output['tablename_List'] as $k => $v){?>
          <option value="<?php echo $v['Name'];?>"><?php echo $v['Name'].'('.$v['Comment'].')';?></option>
          <?php }?>
          </select>
          </td>
          <td class="required"><label style="color: red;" class="tablename_tip"></label></td>
          </tr>
            <tr class="noborder attribute hide">
          <td class="required">
          <label style="line-height: 45px">对应属性列:</label>
          <select name="listname" id="listname">
          <option value=""><?php echo $lang['nc_please_choose'];?>...</option>
          </select>
          <label>操作:</label>
          <select name="operator" id="operater">
          <option value="0">直接替换</option>
          <option value="1">excel替换</option>
          </select>
          </td>
          <td class="required"><label style="color: red;" class="attribute_tip"></label></td>
        </tr>
        <tr class="noborder hide file_upload">
          <td colspan="2" class="required"><label><?php echo $lang['goods_class_import_choose_file'];?>:</label></td>
        </tr>
        <tr class="noborder hide file_upload">
          <td class="vatop rowform"><span class="type-file-box">
            <input type="file" name="csv" id="csv" class="type-file-file"  size="30"  />
            </span></td>
          <td class="vatop tips"><?php echo $lang['goods_class_import_file_tip'];?></td>
        </tr>
        <tr class=" hide file_upload">
          <td colspan="2" class="required"><label><?php echo $lang['goods_class_import_file_type'];?>:</label>
            <a href="<?php echo RESOURCE_SITE_URL;?>/examples/goods_class.csv" class="btns"><span><?php echo $lang['goods_class_import_example_tip'];?></span></a></td>
        </tr>
      </tbody>
      <tfoot>
        <tr class="tfoot">
          <td colspan="2"><a href="JavaScript:void(0);" class="btn" id="formsubmit"><span><?php echo $lang['goods_class_import_import'];?></span></a></td>
        </tr>
      </tfoot>
    </table>
  </form>
</div>

<script type="text/javascript">
    $(function(){
    var textButton="<input type='text' name='textfield' id='textfield1' class='type-file-text' /><input type='button' name='button' id='button1' value='' class='type-file-button' />"
    $(textButton).insertBefore("#csv");

    $("#csv").change(function(){
    $("#textfield1").val($("#csv").val());
    });

    $("#formsubmit").click(function(){
        if(submit()){
            $("#form1").submit();
        }
    })

    //选择操作类型
    $("#type").change(function(){
        var value=$("#type").val();
        if(value != ''){
            if($(".tablename").is('.hide') && value == 2){
                $(".tablename").removeClass('hide');
            }else if(!$(".tablename").is('.hide') && value != 2){
                $(".tablename").addClass('hide');
                if(!$(".attribute").is('.hide'))
                    $(".attribute").addClass('hide');
            }

            if((value == 2 && $("#operator").val() == 0) || value == 3){
                if(!$(".file_upload").is('.hide')){
                    $(".file_upload").addClass('hide');
                }
            }else{
                if($(".file_upload").is('.hide')){
                    $(".file_upload").removeClass('hide');
                }
            }
        }
    });

    //获取选中的table的列名
    $("#tablename").change(function(){
        var checkValue=$("#tablename").val();
        if(checkValue != ''){
            $.ajax({
                url:'<?php echo 'index.php?act=goods_class&op=attributelist'?>',
                type:'POST', //GET
                data:{
                    tablename:checkValue
                },
                dataType: 'json',
                success:function(data){
                    console.log(data);
                    if(data.length > 0){
                        var str = '<option value=""><?php echo $lang['nc_please_choose'];?>...</option>';
                        $(data).each(function(index,element){
                            str += '<option value="'+element+'">'+element+'</option>';
                        });
                        $("#listname").html(str);
                        if($(".attribute").is('.hide')){
                            $(".attribute").removeClass('hide');
                        }
                    }
                },
            })
        }
    })
});
</script> 
<script>
function submit(){
    var type=$("#type").val();
    switch(type){
    case '0':
    case '1': if($("#textfield1").val() != '') return true;else {$(".tips").html("<label style='color:red;'>请选择要上传的文件</label>"); return false;}
    case '2': if($("#tablename").val() == '') {$('.tablename_tip').html("请选择要修改的数据表!");return false;} else if($("#listname").val() == ''){$('.attribute_tip').html("请选择要修改数据表的对应列!");return false;} else if($("#operator").val == '1') if($("#textfield1").val() != '') return true;else {$(".tips").html("<label style='color:red;'>请选择要上传的文件</label>"); return false;} else return true;
    case '3': return true;
    default:$(".type_tip").html("请选择要进行的操作!");return false;
    }
}
</script>

2。后台控制代码(这里用的excel读取插件是phpexcel)

/**
     * 分类导入
     */
    public function goods_class_importOp(){
        $lang  = Language::getLangContent();
        $model_class = Model('goods_class');
        //导入
        if (chksubmit()){
            if(isset($_POST['operator']) && $_POST['operator'] == 0 && $_POST['type'] == 2){
                $obj_cache = Cache::getInstance();
                $compare_array = $obj_cache->get('compareInfo');
                if(empty($compare_array)){
                    showMessage("新旧分类的对照表还没导入,请先导入新旧分类对照表!");
                }else{
                        foreach ($compare_array as $key => $value){
                            $param[$_POST['listname']] = $value[0];
                            $condition = 'where '.$_POST['listname'].' = '.$key;
                            $result = $model_class->updateByTableName($_POST['tablename'],$param,$condition);
                            if(!$result){
                                showMessage("更新数据表失败,请重新操作!");
                            }
                        }
                }
            }
            if($_POST['type'] == 3){
                $result = $this->updateDeep();
                if(!$result)
                    showMessage("更新deep失败,请重新操作!");
                else
                    showMessage("恭喜您,更新deep成功!");
            }else{
                $data= $this->importExecl($_FILES['csv']);
                if($data['error'] == 0){
                    showMessage($data['data']);
                }else{
                switch($_POST['type']){
                    case 0 :$newInfo = $this->addNewClass($data['data'][0]);if(empty($newInfo)) showMessage("新增数据表失败,请重新操作!");break;
                    case 1:$newInfo = $model_class->getNewInfo();$oldInfo = $model_class->getOldInfo();$compare_array = $this->compare($oldInfo,$newInfo,$data['data'][0]);if(empty($compare_array)) showMessage("新旧数据对应表更新失败,请重新操作!");break;
                    case 2: $newInfo = $model_class->getNewInfo();$result = $this->updateData($newInfo,$data['data'][0]);if(!$result)showMessage("更新数据表失败,请重新操作!");break;
                }
    //          var_dump($compare_array);exit;
    //          $this->log(L('goods_class_index_import,goods_class_index_class'),0);
    //          showMessage($lang['goods_class_import_csv_null']);
                showMessage($lang['goods_class_import_succ']);
                }
            }
        }
        //获取数据库全部表名
        $tablename_List = $model_class->getAllTableName();
        Tpl::output('tablename_List', $tablename_List);

        Tpl::output('top_link',$this->sublink($this->links,'goods_class_import'));
        Tpl::showpage('goods_class.import');
    }


public function attributelistOp(){
        if(!isset($_POST['tablename'])){
            echo  '';exit;
        }
        $model_class = Model('goods_class');
        $result = $model_class->getAllAttributeNameByTableName($_POST['tablename']);
        print_r(json_encode($result));exit;
    }

    protected function importExecl($file){

        include(BASE_RESOURCE_PATH.'//phpexcel/PHPExcel.php');
        if(!file_exists($file['tmp_name'])){
            return array("error"=>0,'message'=>'file not found!');
        }

        iconv("gbk","utf8",$file["tmp_name"]);//编码转换

        $type = strtolower( pathinfo($file['name'], PATHINFO_EXTENSION));

        if( $type!='xlsx'&&$type=='xls'&&$type=='csv'){
            return array("error"=>0,'message'=>'Not supported file types!');
        }

        $fileType = PHPExcel_IOFactory::identify($file["tmp_name"]);//判断文件的类型
        $objReader=PHPExcel_IOFactory::createReader($fileType);//创建对象
        try{
            $PHPReader = $objReader->load($file['tmp_name']);
        }catch(Exception $e){}
        if(!isset($PHPReader)) return array("error"=>0,'message'=>'read error!');
        $allWorksheets = $PHPReader->getAllSheets();
        $array = array();
        $i = 0;
        foreach($allWorksheets as $objWorksheet){
            $allRow = $objWorksheet->getHighestRow();//how many rows
            $highestColumn = $objWorksheet->getHighestColumn();//how many columns
            $allColumn = PHPExcel_Cell::columnIndexFromString($highestColumn);
            $array[$i]["Cols"] = $allColumn;
            $array[$i]["Rows"] = $allRow;
            $arr = array();
            $isMergeCell = array();
            foreach ($objWorksheet->getMergeCells() as $cells) {//merge cells看是否有合并单元格,对合并单元格进行处理
                foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cells) as $cellReference) {
                    $isMergeCell[$cellReference] = true;
                }
            }

            for($currentRow = 1 ;$currentRow<=$allRow;$currentRow++){
                $row = array();
                for($currentColumn=0;$currentColumn<$allColumn;$currentColumn++){
                    $cell =$objWorksheet->getCellByColumnAndRow($currentColumn, $currentRow);
                    $afCol = PHPExcel_Cell::stringFromColumnIndex($currentColumn+1);
                    $bfCol = PHPExcel_Cell::stringFromColumnIndex($currentColumn-1);
                    $col = PHPExcel_Cell::stringFromColumnIndex($currentColumn);
                    $address = $col.$currentRow;
                    $value = $objWorksheet->getCell($address)->getValue();
                    //              if(substr($value,0,1)=='='){//遇到公式返回不允许使用公式
                    //                  return array("error"=>0,'message'=>'can not use the formula!');
                    //                  exit;
                    //              }
                    //              if($cell->getDataType()==PHPExcel_Cell_DataType::TYPE_NUMERIC){//读取日期
                    //                  $cellstyleformat=$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat();
                    //                  $formatcode=$cellstyleformat->getFormatCode();
                    //                  if (preg_match('/^([$[A-Z]*-[0-9A-F]*])*[hmsdy]/i', $formatcode)) {
                    //                      $value=gmdate("Y-m-d", PHPExcel_Shared_Date::ExcelToPHP($value));
                    //                  }else{
                    //                      $value=PHPExcel_Style_NumberFormat::toFormattedString($value,$formatcode);
                    //                  }
                    //              }
                    if($isMergeCell[$col.$currentRow]&&$isMergeCell[$afCol.$currentRow]&&!empty($value)){
                        $temp = $value;
                    }elseif($isMergeCell[$col.$currentRow]&&$isMergeCell[$col.($currentRow-1)]&&empty($value)){
                        $value=$arr[$currentRow-1][$currentColumn];
                    }elseif($isMergeCell[$col.$currentRow]&&$isMergeCell[$bfCol.$currentRow]&&empty($value)){
                        $value=$temp;
                    }
                    $row[$currentColumn] = $value;
                }
                $arr[$currentRow] = $row;
            }
            $array[$i]["Content"] = $arr;
            $i++;
        }
        unset($objWorksheet);
        unset($PHPReader);
        unset($PHPExcel);
        unlink($file);
        return array("error"=>1,"data"=>$array);
    }

    protected function addNewClass($sheet){
        if(empty($sheet)){
            return array();
        }
        $model_class = Model('goods_class');
        $res = $model_class->createNewTable();
        if(!$res)
            return array();
        $sheet1 = $sheet;
        $cols = $sheet['Cols'];
        $rows = $sheet['Rows'];
        $sheet = $sheet['Content'];
//      $classArray = array();
        $signArray = array(-1,-1,-1,-1);//标明一,二,三级分类所在列
        $allCatalogsInfo = array();

        for($j = 0; $j < $cols; $j++){
            switch($sheet[1][$j]){
                case '一级分类': $signArray[0] = $j; break;
                case '二级分类': $signArray[1] = $j; break;
                case '三级分类': $signArray[2] = $j; break;
                default: break;
            }
            if (strpos($sheet[1][$j], '对应') !== false) {
                $signArray[3] = $j;
            }
        }
        for ($i = 2; $i <= $rows; $i++){

            if($signArray[0] == -1)
                break;

            if($sheet[$i][$signArray[0]] =="——" || $sheet[$i][$signArray[0]] == '')
                continue;

            $gc_id1 = $this->get_id($sheet[$i][$signArray[0]], $allCatalogsInfo, 0);
//          if(!array_key_exists($gc_id1,$classArray)){
//              $classArray[$gc_id1] = array();
//              $classArray[$gc_id1]['xiaji'] = array();
//              $classArray [$gc_id1] ['id'] = $gc_id1;
//              $classArray [$gc_id1] ['name'] = $sheet[$i][$signArray[0]];
//              $classArray [$gc_id1] ['gc_parent_id'] = 0;
//          }

            if($signArray[1] == -1 || $sheet[$i][$signArray[1]] =="——" || $sheet[$i][$signArray[1]] == '')
                continue;

            $gc_id2 = $this->get_id($sheet[$i][$signArray[1]], $allCatalogsInfo, $gc_id1);
//          if(!array_key_exists($gc_id2,$classArray)){
//              $classArray[$gc_id2] = array();
//              $classArray[$gc_id2]['xiaji'] = array();
//              $classArray [$gc_id2] ['id'] = $gc_id2;
//              $classArray [$gc_id2] ['name'] = $sheet[$i][$signArray[1]];
//              $classArray [$gc_id2] ['gc_parent_id'] = $gc_id1;
//              $classArray [$gc_id1] ['xiaji'] [] = &$classArray [$gc_id2];
//          }

            if($signArray[2] == -1 || $sheet[$i][$signArray[2]] =="——" || $sheet[$i][$signArray[2]] == '')
                continue;

            $gc_id3 = $this->get_id($sheet[$i][$signArray[2]], $allCatalogsInfo, $gc_id2);
//          if(!array_key_exists($gc_id3,$classArray)){
//              $classArray[$gc_id3] = array();
//              $classArray[$gc_id3]['xiaji'] = array();
//              $classArray [$gc_id3] ['id'] = $gc_id3;
//              $classArray [$gc_id3] ['name'] = $sheet[$i][$signArray[2]];
//              $classArray [$gc_id3] ['gc_parent_id'] = $gc_id2;
//              $classArray [$gc_id2] ['xiaji'] [] = &$classArray [$gc_id3];
//          }
        }
        if($signArray[3] != -1){
            $compareclass = $this->compare($oldInfo, $allCatalogsInfo, $sheet1,$signArray);
            return array('type'=>1,'info'=>$compareclass);
        }

        return array('type'=>0, 'info'=>$allCatalogsInfo);
    }

    protected function get_id($classname, &$info, $parent_id){
        $model_class = Model('goods_class');
        if(empty($info) || ((!in_array($classname, $info) && $classname != "——") || (in_array($classname, $info) && ($classname == '其它' || $classname == '其他')))){
            $insert_array = array();
            $insert_array['gc_deep'] = 0;
            $insert_array['gc_name'] = $classname;
            $gc_name_id = $model_class->insert('info_class_name',$insert_array);
            if($gc_name_id){
                $gc_insert_array = array();
                $gc_insert_array['gc_name_id'] = $gc_name_id;
                $gc_insert_array['gc_parent_id'] = $parent_id;
                $gc_id = $model_class->insert('info_class',$gc_insert_array);
                if($gc_id)
                    $info[$gc_id] = $classname;
            }
        }else{
            $gc_id = array_search($classname, $info);
        }
        return $gc_id;
    }

    protected function compare($oldInfo, $newInfo,$sheet,$signArray = array(-1,-1,-1,-1)){
        if(empty($sheet)){
            return array();
        }
        $cols = $sheet['Cols'];
        $rows = $sheet['Rows'];
        $sheet = $sheet['Content'];
        //      $classArray = array();
        $compareInfo = array();
        if($signArray[3] == -1){
            for($j = 0; $j < $cols; $j++){
                switch($sheet[1][$j]){
                    case '一级分类': $signArray[0] = $j; break;
                    case '二级分类': $signArray[1] = $j; break;
                    case '三级分类': $signArray[2] = $j; break;
                    default: break;
                }
                if (strpos($sheet[1][$j], '对应') !== false) {
                    $signArray[3] = $j;
                }
            }
        }
        if($signArray[3] == -1){
            return array();
        }
        for ($i = 2; $i <= $rows; $i++){
            if($sheet[$i][$signArray[3]] =="——")
                continue;
            $old_array = explode( '/',$sheet[$i][$signArray[3]]);
            if($signArray[2] != -1 && $sheet[$i][$signArray[2]] !="——" && $sheet[$i][$signArray[2]] != ''){
                foreach ($old_array as $k =>$v){
                    $old_id = array_search($v, $oldInfo);
                    $new_id = array_search($sheet[$i][$signArray[2]], $newInfo);
                    $compareInfo[$old_id][] = $new_id;
                }
                continue;
            }
            if($signArray[1] != -1 && $sheet[$i][$signArray[1]] !="——" && $sheet[$i][$signArray[1]] != ''){
                foreach ($old_array as $k =>$v){
                    $old_id = array_search($v, $oldInfo);
                    $new_id = array_search($sheet[$i][$signArray[1]], $newInfo);
                    $compareInfo[$old_id][] = $new_id;
                }
                continue;
            }
            if($signArray[0] != -1 && $sheet[$i][$signArray[0]] !="——" && $sheet[$i][$signArray[0]] != ''){
                foreach ($old_array as $k =>$v){
                    $old_id = array_search($v, $oldInfo);
                    $new_id = array_search($sheet[$i][$signArray[0]], $newInfo);
                    $compareInfo[$old_id][] = $new_id;
                }
                continue;
            }
        }
        $obj_cache = Cache::getInstance();
        $obj_cache->set('compareInfo', $compareInfo);
        //$value = $obj_cache->get($key); // 取得缓存
        return $compareInfo;
    }

    protected function updateData($newInfo, $sheet){
        if(empty($sheet)){
            return array();
        }
        $cols = $sheet['Cols'];
        $rows = $sheet['Rows'];
        $sheet = $sheet['Content'];
        $model_class = Model('goods_class');
        for ($i = 1; $i <= $rows; $i++){
            if(!is_numeric($sheet[$i][0]))
                continue;
            $arr = explode("->", $sheet[$i][1]);
            if(end($arr) != '其它' && end($arr) != '其他')
                $newid = array_search(end($arr), $newInfo);
            else{
                $key_arr = array_keys($newInfo,array_pop($arr));
                if(empty($arr)){
                    $newid = end($key_arr);
                }else{

                    $key = array_search(array_pop($arr), $newInfo);
                    foreach ($key_arr as $k => $v){
                        if($v >= $key){
                            $newid = $v;
                            break;
                        }
                    }
                }
            }
            if($newid == false)
                continue;
            $param[$_POST['listname']] = $newid;
            $condition = 'where id = '.$sheet[$i][0];
            $result = $model_class->updateByTableName($_POST['tablename'],$param,$condition);
        }
        return $result;
    }

    protected function updateDeep(){
        //更新一级分类的deep
        $model_class = Model('goods_class');
        $sql = "update btb_info_class_name bisn left join btb_info_class bis on bis.gc_name_id = bisn.gc_name_id set bisn.gc_deep = 1 where bis.gc_parent_id = 0";
        $result = $model_class->excute($sql);

        if(!$result){
            return false;
        }
        $sqll = "select gc_id from btb_info_class bis left join btb_info_class_name bisn on bis.gc_name_id = bisn.gc_name_id where bis.gc_parent_id = 0";
        $arr = $model_class->selectWithSql($sqll);
        if(empty($arr))
            return false;

        $ids = array_map('array_shift',$arr);
        $sqlll = "update btb_info_class_name bisn left join btb_info_class bis on bis.gc_name_id = bisn.gc_name_id set bisn.gc_deep = 2 where bis.gc_parent_id in (".implode(',', $ids).")";
        $ret = $model_class->excute($sqlll);
        if(!$ret)
            return false;
        $sqllll = "update btb_info_class_name set gc_deep = 3 where gc_deep = 0";
        $rett = $model_class->excute($sqllll);
        if($rett)
            return true;
        return false;
    }

在这里,可以看到我用到了php的缓存机制生成了一个新旧分类id对照数组的cache,至于用处,就是为了在更新数据的时候能够更快速(删除分类的时候亦可以使用,删除分类的代码我就不上了,要是有想要的童鞋,我再单给吧,其实自己写也很简单的)。
3。model代码(贴几个代表的吧。不然太多了。。。)

  /**
     * 获取数据库中所有表的表名
     */
    public function getAllTableName(){
        //$result = Db::showTables();
        $result = Db::showTableStatus();
        return $result;
    }

    /**
     * 获取指定数据表的所有属性列
     */
    public function getAllAttributeNameByTableName($tablename){
        $result = Db::showColumnswithpre($tablename);
        return $result;
    }

4。DB代码(这里我写的是原生的php操作数据库的代码,用框架代替操作的童鞋自行查看框架文档哦)

/**
     * 列出所有表
     *
     * @return array
     */
    public static function showTables($host = 'slave'){
        self::connect($host);
        $sql = 'SHOW TABLES';
        $result = self::query($sql,$host);
        $array = array();
        while ($tmp=mysqli_fetch_array($result,MYSQLI_ASSOC)){
            $array[] = $tmp;
        }
        return $array;
    }

    /**
     * 
     * @param string $host
     * @return array
     */
    public static function showTableStatus($host = 'slave'){
        self::connect($host);
        $sql = 'show table status';
        $result = self::query($sql,$host);
        $array = array();
        while ($tmp=mysqli_fetch_array($result,MYSQLI_ASSOC)){
            $array[] = $tmp;
        }
        return $array;
    }

    /**
     * 显示建表语句
     * 
     * @param string $table
     * @return string
     */
    public static function showCreateTable($table, $host = 'slave'){
        self::connect($host);
        $sql = 'SHOW CREATE TABLE '.$GLOBALS['config']['tablepre'].$table;
        $result = self::query($sql,$host);
        $result = mysqli_fetch_array($result,MYSQLI_ASSOC);
        return $result['Create Table'];
    }

    /**
     * 显示表结构信息
     * 
     * @param string $table
     * @return array
     */
    public static function showColumns($table, $host = 'slave'){
        self::connect($host);
        $sql = 'SHOW COLUMNS FROM `'.$GLOBALS['config']['tablepre'].$table.'`';
        $result = self::query($sql,$host);
        $array = array();
        while ($tmp=mysqli_fetch_array($result,MYSQLI_ASSOC)){
            $array[$tmp['Field']] = array(
                'name'    => $tmp['Field'],
                'type'    => $tmp['Type'],
                'null'    => $tmp['Null'],
                'default' => $tmp['Default'],
                'primary' => (strtolower($tmp['Key']) == 'pri'),
                'autoinc' => (strtolower($tmp['Extra']) == 'auto_increment'),
            );
        }
        return $array;
    }

    /**
     * 显示表结构信息带前缀
     *
     * @param string $table
     * @return array
     */
    public static function showColumnswithpre($table, $host = 'slave'){
        self::connect($host);
        $sql = 'SHOW COLUMNS FROM `'.$table.'`';
        $result = self::query($sql,$host);
        $array = array();
        while ($tmp=mysqli_fetch_array($result,MYSQLI_ASSOC)){
            $array[] =$tmp['Field'];
        }
        return $array;
    }

就此,简单的分类管理就完成了。别看着代码就一点点,也是花了好几天搭建出来的哟~有什么疑问的话可以私信我或评论,看到肯定会回的。

在最后,再说几个小Tip吧:
1。若数据修改表中的用来替换旧分类的新分类出现重名的情况如何处理:就以最容易重复出现的“其它”这个为例吧。我是这样处理的,先用array_keys($newInfo,array_pop($arr)),找出值相同的key数组,即重名的“其它”所对应的id数组。然后根据它的父类id必然在它的id前面(如果时通过excel导入的话一定是这样,非此种情况请自行增加判断条件),从key数组中找到比父类id大的第一个key,就是正确的替换id。
2。PHP获取二维数组中某一列的值集合。文中我用的$ids = array_map('array_shift',$arr);,其实方法有很多。大家可以参考这一篇文章,地址是:http://www.jb51.net/article/77005.htm。(为了防止文章地址挂掉,我会在本文末尾附上该文章内容)。感谢分享的大大~
3。善用cache来减少查库和不必要的foreach,但要注意,此法适用于数据量相对较小的时候。

文尾附录(注明:非原创,原文地址:http://www.jb51.net/article/77005.htm):
PHP还是比较常用的,于是我研究了一下PHP二维数组。在处理php数组的时候,有一种需求特别的频繁,如下二维数组:

$arr = array(
1=>array(
'id' => 5,
'name' => '张三'
),
2=>array(
'id' => 6,
'name' => '李四'
)
);

目的就是要取到key为name的集合,得到这个结果:

$arr2 = array(
0=>'张三',
1=>'李四'
);

这里有几种方法:

1:最简单的,foreach遍历数组:

foreach ($arr as $key => $value) {
$arr2[] = $value['name'];
}

2:代码量稍微少一点的代码,使用了 array_map 这个php方法:

$arr2 = array_map('array_shift',$arr);

意为把 arr arr2的键仍是原数组$arr的键

2.1:在方法2的基础上,可以稍微开一下脑洞,如果需要获取的是二维数组的每一项的开头列或结尾列,也可以这样做:

$arr2 = array_map('reset',$arr);
$arr2 = array_map('end',$arr);

哈哈,也是很方便的

3:还可以使用 array_reduce方法,不过代码略多,不过这个方法的想象空间(针对别的数组取值操作)还是蛮大的:

$arr2 = array_reduce($arr, create_function('$result, $v', '$result[] = $v["name"];return $result;'));

array_reduce方法用回调函数迭代地将对数组的值进行操作,而create_function用于一个匿名方法做回调用,这个匿名方法的参数$result为上一次迭代产生的值,$v是当前的值,内部实现既为获取到数组$arr每一项的”name”的值并push到新$result数组;

4:最后这个终极方法实在是太爽了,一个方法就搞定,而且非常灵活:

 $arr2 = array_column($arr, 'name');

第二个参数为想要获取的那一列的键名,是不是很方便呢,不过这个方法有个限制,就是php版本必须 >= 5.5.0,在陈旧项目中使用这个方法还是得斟酌一下哈

PS: php中遍历二维数组的几种方式

<?php
//使用for循环遍历
$arr2=array(array("张三","20","男"),array("李四","25","男"),array("王五","19","女"),array("赵六","25","女"));
echo "<table border=2 bordercolor=red><tr><td>姓名</td><td>年龄</td& gt;<td>性别</td></tr>";
for($i=0;$i<4;$i++){
echo "<tr>";
for($j=0;$j<3;$j++){
  echo "<td>";
  echo $arr2[$i][$j];
  echo "</td>";
}
echo "</tr>";
echo "<br>";
}
echo "</table>";
?>
//使用foreach遍历
<?php
$arr = array('one'=>array('name'=>'张三','age'=>'23','sex'=>'男'),
  'two'=>array('name'=>'李四','age'=>'43','sex'=>'女'),
  'three'=>array('name'=>'王五','age'=>'32','sex'=>'男'),
  'four'=>array('name'=>'赵六','age'=>'12','sex'=>'女'));
foreach($arr as $k=>$val){
  echo $val['name'].$val['age'].$val['sex']."<br>";
}
echo "<p>";
?>
<?php
$arr = array('one'=>array('name'=>'张三','age'=>'23','sex'=>'男'),
  'two'=>array('name'=>'李四','age'=>'43','sex'=>'女'),
  'three'=>array('name'=>'王五','age'=>'32','sex'=>'男'),
  'four'=>array('name'=>'赵六','age'=>'12','sex'=>'女'));
foreach($arr as $key=>$value){
foreach($value as $key2=>$value2){
  echo $value2;
}
echo "<br>";
}
?>

猜你喜欢

转载自blog.csdn.net/sinat_29673403/article/details/72476804