奪命雷公狗ThinkPHP項目之----商城9商品後臺無限極分類

無限極分類,幾乎在每一個網站上都會用到的,所以而重要。php

 

先來對數據表進行分析css

parent_id:表示當前分類的父id,他是實現無限級分類的關鍵html

 

無限級分類,主要從兩個方面進行考慮的。數據庫

1.數據庫的設計,表中的parent_id字段。數組

2.在程序的層面上,來完成,使用遞歸。app

咱們只要理解下面這張圖便可瞭解無限極分類的大部份了post

上面的這三表是否能夠變成下面這一張表呢?測試

這樣的話關聯起來是否是更加方便呢?網站

說白了也就是PID就是他的老爸的ID一直到PID爲0這就到了頂級分類ui

 

添加分類,首先是要載入添加的表單,確保表單的name和字段一致,首先在view裏面建立一個category文件夾在裏面將模版放進去,咱們先來寫add.html的文件

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SHOP 管理中心 - 添加分類 </title>
<meta name="robots" content="noindex, nofollow">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="__ADMIN__/styles/general.css" rel="stylesheet" type="text/css" />
<link href="__ADMIN__/styles/main.css" rel="stylesheet" type="text/css" />
</head>
<body>

<h1>
<span class="action-span"><a href="index.php?p=admin&c=category&a=index">商品分類</a></span>
<span class="action-span1"><a href="index.php?act=main">SHOP 管理中心</a> </span><span id="search_id" class="action-span1"> - 添加分類 </span>
<div style="clear:both"></div>
</h1>
<!-- start add new category form -->
<div class="main-div">
  <form action="" method="post" name="theForm" enctype="multipart/form-data" onsubmit="return validate()">
     <table width="100%" id="general-table">
        <tbody>
            <tr>
                <td class="label">分類名稱:</td>
                <td><input type="text" name="cat_name" maxlength="20" value="" size="27"> <font color="red">*</font></td>
            </tr>
            <tr>
                <td class="label">上級分類:</td>
                <td>
                    <select name="parent_id">
                        <option value="0">頂級分類</option>
                        <volist name="cats" id='vo'>
                            <option value="{$vo['cat_id']}">{$vo['cat_name']}</option>
                        </volist>
                    </select>
                </td>
            </tr>

            <tr id="measure_unit">
                <td class="label">數量單位:</td>
                <td><input type="text" name="unit" value="" size="12"></td>
            </tr>
            <tr>
                <td class="label">排序:</td>
                <td><input type="text" name="sort_order" value="50" size="15"></td>
            </tr>

            <tr>
                <td class="label">是否顯示:</td>
                <td><input type="radio" name="is_show" value="1" checked="true"><input type="radio" name="is_show" value="0"></td>
            </tr>
      <tr>
        <td class="label">分類描述:</td>
        <td>
          <textarea name="cat_desc" rows="6" cols="48"></textarea>
        </td>
      </tr>
      </tbody></table>
      <div class="button-div">
        <input type="submit" value=" 肯定 ">
        <input type="reset" value=" 重置 ">
      </div>
  </form>
</div>



<div id="footer">
    版權全部 &copy; 2014-2016 奪命雷公狗 - 技術總結 - 
</div>

</div>

</body>
</html>

 

這裏完成了後,下一步就是開始寫CategoryController.class.php控制器裏面的add方法了

public function add(){
            if(IS_POST){
                //分類信息入庫
                $data['cat_name'] = I('cat_name');
                $data['parent_id'] = I('parent_id',0,'int');//parent_id一般是整型,因此作個小處理
                $data['cat_desc'] = I('cat_desc');
                $data['unit'] = I('unit');//數量
                $data['is_show'] = I('is_show');
                $data['sort_order'] = I('sort_order');

                $categoryModel = D('category');
                if($categoryModel->create($data)){
                    //驗證經過
                    if($categoryModel->add()){
                        //插入成功
                        $this -> success('分類信息添加成功',U('index'),1);
                    }else{
                        //插入失敗
                        $this -> error('分類信息添加失敗');
                    }
                }else{
                    //驗證失敗
                    $this -> error($categoryModel->getError());
                }
                return;
            }
            //載入添加分類頁面
            //獲取全部的分類
            $cats = M('category')->select();
            $this -> assign('cats',$cats);
            $this -> display();
        }

 

在這的驗證是經過model層裏面進行驗證的,那麼咱們下一步就是在model文件夾裏建立一個CategoryModel.class.php的文件,代碼以下所示

 

<?php
    //商品分類模型
    namespace Admin\Model;
    use Think\Model;
    class CategoryModel extends Model{
        //自動驗證
        protected $_validate = array(
            array('cat_name','require','商品名稱不能爲空'),
        );
    }

 

好像是完成了噢,不過一測試,發現裏面的無限極分類效果是出來了,可是實在很差看,什麼都逼在同個水平線下,那麼咱們的解決方案是經過樹狀方式來進行解決問題

 

咱們作目錄樹的時候要玩到遞歸,遞歸說白了就是讓他重複幹事情的,給定一個pid,找他的後代節點,找到保存起來。

條件pid等於給定的id。

最終目的要成爲這樣:

先在model層裏面開幹,

<?php
    //商品分類模型
    namespace Admin\Model;
    use Think\Model;
    class CategoryModel extends Model{
        //自動驗證
        protected $_validate = array(
            array('cat_name','require','商品名稱不能爲空'),
        );

        //定義一個方法,獲取樹狀的分類信息
        public function catTree(){
            $cats = $this->select();
            return $this->tree($cats);
        }

        //定義一個方法,對給定的數組,遞歸造成樹
        public function tree($arr,$pid=0,$level=0){
            static $tree = array();
            foreach($arr as $v){
                if($v['parent_id']==$pid){
                    //說明找到,保存
                    $v['level'] = $level;
                    $tree[] = $v;
                    //繼續找
                    $this -> tree($arr,$v['cat_id'],$level+1);
                }
            }
            return $tree;
        }
    }

 

而後在控制器下改下他的查詢方式,代碼以下:

public function add(){
            if(IS_POST){
                //分類信息入庫
                $data['cat_name'] = I('cat_name');
                $data['parent_id'] = I('parent_id',0,'int');//parent_id一般是整型,因此作個小處理
                $data['cat_desc'] = I('cat_desc');
                $data['unit'] = I('unit');//數量
                $data['is_show'] = I('is_show');
                $data['sort_order'] = I('sort_order');

                $categoryModel = D('category');
                if($categoryModel->create($data)){
                    //驗證經過
                    if($categoryModel->add()){
                        //插入成功
                        $this -> success('分類信息添加成功',U('index'),1);
                    }else{
                        //插入失敗
                        $this -> error('分類信息添加失敗');
                    }
                }else{
                    //驗證失敗
                    $this -> error($categoryModel->getError());
                }
                return;
            }
            //載入添加分類頁面
            //獲取全部的分類
            $cats = D('category')->catTree();
            $this -> assign('cats',$cats);
            $this -> display();
        }

 

最後在add.html模版下修改下便可

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SHOP 管理中心 - 添加分類 </title>
<meta name="robots" content="noindex, nofollow">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="__ADMIN__/styles/general.css" rel="stylesheet" type="text/css" />
<link href="__ADMIN__/styles/main.css" rel="stylesheet" type="text/css" />
</head>
<body>

<h1>
<span class="action-span"><a href="index.php?p=admin&c=category&a=index">商品分類</a></span>
<span class="action-span1"><a href="index.php?act=main">SHOP 管理中心</a> </span><span id="search_id" class="action-span1"> - 添加分類 </span>
<div style="clear:both"></div>
</h1>
<!-- start add new category form -->
<div class="main-div">
  <form action="" method="post" name="theForm" enctype="multipart/form-data" onsubmit="return validate()">
     <table width="100%" id="general-table">
        <tbody>
            <tr>
                <td class="label">分類名稱:</td>
                <td><input type="text" name="cat_name" maxlength="20" value="" size="27"> <font color="red">*</font></td>
            </tr>
            <tr>
                <td class="label">上級分類:</td>
                <td>
                    <select name="parent_id">
                        <option value="0">頂級分類</option>
                        <volist name="cats" id='vo'>
                            <option value="{$vo['cat_id']}">{$vo['level']|str_repeat="&nbsp;&nbsp;&nbsp;",###}{$vo['cat_name']}</option>
                        </volist>
                    </select>
                </td>
            </tr>

            <tr id="measure_unit">
                <td class="label">數量單位:</td>
                <td><input type="text" name="unit" value="" size="12"></td>
            </tr>
            <tr>
                <td class="label">排序:</td>
                <td><input type="text" name="sort_order" value="50" size="15"></td>
            </tr>

            <tr>
                <td class="label">是否顯示:</td>
                <td><input type="radio" name="is_show" value="1" checked="true"><input type="radio" name="is_show" value="0"></td>
            </tr>
      <tr>
        <td class="label">分類描述:</td>
        <td>
          <textarea name="cat_desc" rows="6" cols="48"></textarea>
        </td>
      </tr>
      </tbody></table>
      <div class="button-div">
        <input type="submit" value=" 肯定 ">
        <input type="reset" value=" 重置 ">
      </div>
  </form>
</div>



<div id="footer">
    版權全部 &copy; 2014-2016 奪命雷公狗 - 技術總結 - 
</div>

</div>

</body>
</html>

 

添加頁完事,那麼下一步就是列表顯示頁了,先寫index方法由於直接賦值剛纔那個過來便可

 

//顯示分類
        public function index(){
            $cats = D('category')->catTree();
            $this -> assign('cats',$cats);
            $this -> display();
        }

 

而後在view下的index.html模版裏進行遍歷

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SHOP 管理中心 - 商品分類 </title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="__ADMIN__/styles/general.css" rel="stylesheet" type="text/css" />
<link href="__ADMIN__/styles/main.css" rel="stylesheet" type="text/css" />
</head>
<body>

<h1>
<span class="action-span"><a href="__MODULE__/category/add">添加分類</a></span>
<span class="action-span1"><a href="index.php?p=admin&c=index&a=index">SHOP 管理中心</a> </span><span id="search_id" class="action-span1"> - 商品分類 </span>
<div style="clear:both"></div>
</h1>

<form method="post" action="" name="listForm">
<!-- start ad position list -->
    <div class="list-div" id="listDiv">
        <table width="100%" cellspacing="1" cellpadding="2" id="list-table">
            <tbody>
                <tr>
                    <th>分類名稱</th>
                    <th>商品數量</th>
                    <th>數量單位</th>
                    <th>導航欄</th>
                    <th>是否顯示</th>
                    <th>價格分級</th>
                    <th>排序</th>
                    <th>操做</th>
                </tr>
        <volist name="cats" id="vo">
                <tr align="center" class="0" id="0_1">
          <td align="left" class="first-cell">
          {$vo['level']|str_repeat="&nbsp;&nbsp;&nbsp;&nbsp;",###}
                        <img src="__ADMIN__/images/menu_minus.gif" id="icon_0_1" width="9" height="9" border="0" style="margin-left:0em" onclick="rowClicked(this)">
                        <span><a href="goods.php?act=list&amp;cat_id=1">{$vo['cat_name']}</a></span>
                     </td>
                    
          <td width="10%">0</td>
                    
          <td width="10%"><span onclick="listTable.edit(this, 'edit_measure_unit', 1)" title="點擊修改內容" style="">{$vo['unit']}</span></td>
                    
          <td width="10%"><img src="__ADMIN__/images/no.gif" onclick="listTable.toggle(this, 'toggle_show_in_nav', 1)"></td>
                    
          <td width="10%"><img src="
            <if condition="$vo['is_show'] eq 1">
            __ADMIN__/images/yes.gif"
            <else />
            __ADMIN__/images/no.gif"
            </if>
             onclick="listTable.toggle(this, 'toggle_is_show', 1)"></td>
                    
          <td><span onclick="listTable.edit(this, 'edit_grade', 1)" title="點擊修改內容" style="">5</span></td>
                    
          <td width="10%" align="right"><span onclick="listTable.edit(this, 'edit_sort_order', 1)" title="點擊修改內容" style="">{$vo['sort_order']}</span></td>
                    <td width="24%" align="center">
                        <a href="category.php?act=move&amp;cat_id=1">轉移商品</a> |
                        <a href="__CONTROLLER__/edit/id/{$vo['cat_id']}">編輯</a> |
                        <a href="__CONTROLLER__/del/id/{$vo['cat_id']}" onclick="return confirm('您是否真的刪除這個品牌呢?')" title="移除">移除</a>
                    </td>
                </tr>
        </volist>
    </tbody>
  </table>
</div>
</form>

  </table>
</div>
</form>


<div id="footer">
    版權全部 &copy; 2014-2016 奪命雷公狗 - 技術總結 - </div>
</div>
 <script>
    /**
 * 摺疊分類列表
 */
var imgPlus = new Image();
imgPlus.src = "application/views/admin/images/menu_plus.gif";

function rowClicked(obj)
{
  // 當前圖像
  img = obj;
  // 取得上二級tr>td>img對象
  obj = obj.parentNode.parentNode;
  // 整個分類列表表格
  var tbl = document.getElementById("list-table");
  // 當前分類級別
  var lvl = parseInt(obj.className);
  // 是否找到元素
  var fnd = false;
  var sub_display = img.src.indexOf('menu_minus.gif') > 0 ? 'none' : 'table-row' ;
  // 遍歷全部的分類
  for (i = 0; i < tbl.rows.length; i++)
  {
      var row = tbl.rows[i];
      if (row == obj)
      {
          // 找到當前行
          fnd = true;
          //document.getElementById('result').innerHTML += 'Find row at ' + i +"<br/>";
      }
      else
      {
          if (fnd == true)
          {
              var cur = parseInt(row.className);
              var icon = 'icon_' + row.id;
              if (cur > lvl)
              {
                  row.style.display = sub_display;
                  if (sub_display != 'none')
                  {
                      var iconimg = document.getElementById(icon);
                      iconimg.src = iconimg.src.replace('plus.gif', 'minus.gif');
                  }
              }
              else
              {
                  fnd = false;
                  break;
              }
          }
      }
  }

  for (i = 0; i < obj.cells[0].childNodes.length; i++)
  {
      var imgObj = obj.cells[0].childNodes[i];
      if (imgObj.tagName == "IMG" && imgObj.src != 'application/views/admin/images/menu_arrow.gif')
      {
          imgObj.src = (imgObj.src == imgPlus.src) ? 'application/views/admin/images/menu_minus.gif' : imgPlus.src;
      }
  }
}
</script>
</body>
</html>

 

效果以下圖所示:

 

顯示列表也有了,那麼下一步就開始寫更新頁了

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SHOP 管理中心 - 添加分類 </title>
<meta name="robots" content="noindex, nofollow">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="__ADMIN__/styles/general.css" rel="stylesheet" type="text/css" />
<link href="__ADMIN__/styles/main.css" rel="stylesheet" type="text/css" />
</head>
<body>

<h1>
<span class="action-span"><a href="index.php?p=admin&c=category&a=index">商品分類</a></span>
<span class="action-span1"><a href="index.php?act=main">SHOP 管理中心</a> </span><span id="search_id" class="action-span1"> - 添加分類 </span>
<div style="clear:both"></div>
</h1>
<!-- start add new category form -->
<div class="main-div">
  <form action="category.php" method="post" name="theForm" enctype="multipart/form-data" onsubmit="return validate()">
     <table width="100%" id="general-table">
        <tbody>
            <tr>
                <td class="label">分類名稱:</td>
                <td><input type="text" name="cat_name" maxlength="20" value="{$cat['cat_name']}" size="27"> <font color="red">*</font></td>
            </tr>
            <tr>
                <td class="label">上級分類:</td>
                <td>
                    <select name="parent_id">
                        <option value="0">頂級分類</option>
                        <volist name="cats" id='vo'>
                            <option value="{$vo['cat_id']}"
                            <if condition="$vo['cat_id'] eq $cat['parent_id']" >selected="selected"</if>
                            >{$vo['level']|str_repeat="&nbsp;&nbsp;&nbsp;",###}{$vo['cat_name']}</option>
                        </volist>     
                    </select>
                </td>
            </tr>

            <tr id="measure_unit">
                <td class="label">數量單位:</td>
                <td><input type="text" name="unit" value="{$cat['unit']}" size="12"></td>
            </tr>
            <tr>
                <td class="label">排序:</td>
                <td><input type="text" name="sort_order" value="{$cat['sort_order']}" size="15"></td>
            </tr>

            <tr>
                <td class="label">是否顯示:</td>
                <td><input type="radio" name="is_show" value="1" checked="true"
                <if condition="$cat['is_show'] eq 1">checked="checked"</if>
                > 是<input type="radio" name="is_show" value="0"
                <if condition="$cat['is_show'] eq 0">checked="checked"</if>
                > 否  </td>
            </tr>
            <tr>
                <td class="label">是否顯示在導航欄:</td>
                <td><input type="radio" name="show_in_nav" value="1"><input type="radio" name="show_in_nav" value="0" checked="true"></td>
            </tr>
            <tr>
                <td class="label">設置爲首頁推薦:</td>
                <td>
                    <input type="checkbox" name="cat_recommend[]" value="1"> 精品          
                    <input type="checkbox" name="cat_recommend[]" value="2"> 最新          
                    <input type="checkbox" name="cat_recommend[]" value="3"> 熱門       
                </td>
            </tr>
      <tr>
        <td class="label">分類描述:</td>
        <td>
          <textarea name="cat_desc" rows="6" cols="48">{$cat['cat_desc']}</textarea>
        </td>
      </tr>
      </tbody></table>
      <div class="button-div">
        <input type="submit" value=" 肯定 ">
        <input type="reset" value=" 重置 ">
      </div>
      <input type="hidden" name="cat_id" value="{$cat['cat_id']}" />
  </form>
</div>



<div id="footer">
    版權全部 &copy; 2014-2016 奪命雷公狗 - 技術總結 - 
</div>

</div>

</body>
</html>

 

要注意,在編輯的表單中必定要傳cat_id,不然更新會失敗

 <input type="hidden" name="cat_id" value="{$cat['cat_id']}" />

 

 

注意:在更新的時候,若是把當前分類或則其子分類做爲上級分類,就會出現邏輯錯誤..

因此咱們要先到model裏面定義一個方法,讓他不能隨便讓他的當前分類或者子分類做爲上級分類,不然就會出現邏輯上的錯誤。。

在CategoryModel.class.php裏面定義一個方法,代碼以下所示:

//給定一個分類,找其後代分類的cat_id,包括他本身
        public function getSubIds($cat_id){
            $cats = $this -> select();
            $list = $this -> tree($cats,$cat_id);
            $res = array();
            foreach($list as $v){
                $res[] = $v['cat_id'];
            }
            //把cat_id追加到數組
            $res[] = $cat_id;
            return $res;
        }

 

讓後會控制器下定義edit方法,代碼以下所示:

//修改分類
        public function edit(){
            $cat_id = I('id');
            if(IS_POST){
                //更新分類
                $data['cat_name'] = I('cat_name');
                $data['parent_id'] = I('parent_id',0,'int');//parent_id一般是整型,因此作個小處理
                $data['cat_desc'] = I('cat_desc');
                $data['unit'] = I('unit');//數量
                $data['is_show'] = I('is_show');
                $data['sort_order'] = I('sort_order');
                $data['cat_id'] = I('cat_id');
                $categoryModel = D('category');

                $ids = $categoryModel->getSubIds($data['cat_id']);
                if(in_array($data['parent_id'],$ids)){
                    $this -> error('抱歉,不能把當前分類及其子分類做爲其上級分類');
                }

                if($categoryModel->create($data)){
                    //驗證經過
                    if($categoryModel->save()){
                        //插入成功
                        $this -> success('分類信息修改爲功',U('index'),1);
                    }else{
                        //插入失敗
                        $this -> error('分類信息修改失敗');
                    }
                }else{
                    //驗證失敗
                    $this -> error($categoryModel->getError());
                }
                return;
            }
            $cat = M('category')->find($cat_id);
            $cats = D('category')->catTree();
            $this -> assign('cats',$cats);
            $this -> assign('cat',$cat);
            $this -> display();
        }

 

 

修改也好了,那麼就差最後一步了,還差刪除分類的了,代碼以下所示:

//刪除分類
        public function del(){
            $cat_id = I('id',0,'int');
            $categoryModel = D('category');
            $ids = $categoryModel->getSubIds($cat_id);//這裏的目的就是查下有沒有子類
            if(count($ids)>1){
                $this ->error("該分類下面還存在子分類,請處理好了再來");
            }
            if(M('category')->delete($cat_id)){
                $this -> success('刪除成功',U('index'),1);
            }else{
                $this ->error('刪除失敗');
            }
        }
相關文章
相關標籤/搜索