你們好,我是軍哥,英文名:JayJun,一直想跟大夥交流一下學習和使用CI的心得和經驗,最近也在用CI寫一個在線書城項目,已經完成80%,其中有用到無限分類,關於無限分類,有許多的實現方式,今個呢,軍哥,跟你們先分享本身寫的無限分類類庫,只適合CI框架喲,固然你也能夠修改後使用到其它地方,接着咱們會在CI框架中應用一下(詳見附件中代碼示例)。這裏要求你有必定的面向對象基礎,固然瞭解和熟悉CI(或其它PHP框架)就更好啦。 javascript
另外,軍哥在代碼中應用了市面上熱門的一個前端UI框架——bootstarp,這個框架在爲咱們實現頁面樣式方面是表現的至關給力!詳見:bootstrap前端UI框架中文版官網。 php
好了,不廢話啦,軍哥語文學滴很差(小學沒少挨老師打手掌心呀),就直接上代碼了。有學習和研究CI的,歡迎拍磚!!! css
一、先看效果,有圖有真相; html
分頁顯示頁: 前端
添加分類頁: java
編輯分類頁: git
二、控制器(源碼在 application/controllers 文件夾); github
//無限分類控制器功能 class cate extends CI_Controller { private $_cate_url = 'cate/'; //無限分類視圖路徑 public function __construct() { parent::__construct(); $this->base_url = $this->config->item("base_url"); $this->load->library('category'); } //顯示分類 public function index() { $data['base_url'] = $this->base_url; $data['tree_str'] = $this->category->getListStr(); $this->load->view($this->_cate_url.'cate_index',$data); } //編輯分類 public function edit($cid = '') { $data['base_url'] = $this->base_url; if ($cid != '') { $query = $data['post'] = $this->category->fetchOne($cid); $pid = $query['fatherId']; $data['option_str'] = $this->category->getOptionStr(0,true,0,false,$pid); } else { $data['option_str'] = $this->category->getOptionStr(0,true,0,false,0); } $this->load->view($this->_cate_url.'cate_edit',$data); } //執行插入分類操做 public function insert() { //獲取表單提交的信息 $fatherId = $this->input->post('fatherId'); $cateName = $this->input->post('cateName'); $content = $this->input->post('content'); $sort = $this->input->post('sort'); $display = $this->input->post('display'); if ($this->category->addCategory($fatherId,$cateName,$content,$sort,$display) > 0) { echo "<script language=\"javascript\">alert('添加成功!')</script>"; } else { echo "<script language=\"javascript\">alert('添加失敗!')</script>"; } echo "<script language=\"javascript\">history.go(-1);</script>"; } //執行編輯操做 function update($cid = '') { $cid = ($cid === '') ? $this->input->post('cid') : $cid; if ($cid !== '') { //獲取表單提交的信息 $fatherId = $this->input->post('fatherId'); $cateName = $this->input->post('cateName'); $content = $this->input->post('content'); $sort = $this->input->post('sort'); $display = $this->input->post('display'); if ($this->category->editCategory($cid,$fatherId,$cateName,$content,$sort,$display) > 0) { echo "<script language=\"javascript\">alert('更新成功!')</script>"; } else { echo "<script language=\"javascript\">alert('更新失敗!')</script>"; } } echo "<script language=\"javascript\">history.go(-1);</script>"; } //執行刪除操做 function delete($cid = '') { if ($cid !== '') { if ($this->category->delCategory($cid) > 0) { echo "<script language=\"javascript\">alert('刪除成功!')</script>"; } else { echo "<script language=\"javascript\">alert('刪除失敗!')</script>"; } } echo "<script language=\"javascript\">history.go(-1);</script>"; } }三、無限分類類庫(源碼在 application/libraries 文件夾);
/*==================================================================*/ /* 文件名:Category.php */ /* 功能:實現無限分類的增刪改查,用於codeigniter框架, 也能夠修改後用於其它用途。 */ /* 做者:jayjun /* QQ:413920268 */ /* 建立時間:2012-08-29 */ /* 最後修改時間:2012-08-31 */ /* copyright (c)2012 jayjun0805@sina.com */ /*==================================================================*/ if (!defined('BASEPATH')) exit('No direct script access allowed'); class Category { private $CI; //CI對象 private $tableName; //要操做的表名 //表的七個字段 private $cid; //分類ID private $fatherId; //父分類ID private $cateName; //分類名稱 private $sort; //分類排序,在同一父級下有多級時,用於排序 private $content; //分類介紹 private $level; //分類等級,即當前目錄的級別 private $display; //分類顯示狀態 //所取分類的深度 private $depth = 0; private $startLevel = 0; /** * 構造函數 * @param $arr 參數包括表名,及分類表的七個字段名,若是沒有定義,則採用默認, * 默認值 * 表名:category * 分類ID:cid * 父ID:fatherId * 分類名稱:cateName * 分類排序:sort * 分類介紹:content * 分類等級:level * 分類顯示狀態:display */ public function __construct($arr = array()) { //經過引用的方式賦給變量來初始化原始的CodeIgniter對象 $this->CI = &get_instance(); //初始化表參數 $this->tableName = (isset($arr['tableName'])) ? $arr['tableName'] : 'category'; $this->cid = (isset($arr['cid'])) ? $arr['cid'] : 'cid'; $this->fatherId = (isset($arr['fatherId'])) ? $arr['fatherId'] : 'fatherId'; $this->cateName = (isset($arr['cateName'])) ? $arr['cateName'] : 'cateName'; $this->sort = (isset($arr['sort'])) ? $arr['sort'] : 'sort'; $this->content = (isset($arr['content'])) ? $arr['content'] : 'content'; $this->level = (isset($arr['level'])) ? $arr['level'] : 'level'; $this->display = (isset($arr['display'])) ? $arr['display'] : 'display'; } /** * 從數據庫取全部分類數據,返回數組 */ public function fetchData($display) { if ($display) { $query = $this->CI->db->get_where($this->tableName,array($this->display => 0)); } else { $query = $this->CI->db->get($this->tableName); } return $query->result_array(); } /** *取某一條分類數據 *@param $cid 分類ID */ public function fetchOne($cid) { $this->CI->db->where($this->cid,$cid); $query = $this->CI->db->get($this->tableName); return $query->row_array(1); } /** *取出全部分類信息,返回數組,包括分類名稱,通常用在select標籤中顯示 * @param $fatherId 父類ID * @param $withself 查下級分類的時候,是否包含本身,默認false不包含。 * @param $depth 所取分類的深度,值爲0表示不限深度,會取全部的子分類。 * @param $display 分類顯示狀態, */ public function getAllCategory($fatherId = 0,$withself = false,$depth = 0,$display = false) { $result = array(); $resArr = $this->fetchData($display); //獲取全部分類信息 // p($resArr); if($fatherId == 0 && $withself) { $root = array( $this->cid => 0, $this->fatherId => -1, $this->cateName => '根目錄', $this->level => 0, $this->sort => 0 ); array_unshift($resArr, $root); } //p($resArr); if (empty($resArr)) { return array(); } //取得根目錄 foreach($resArr as $item) { if ($item[$this->fatherId] == $fatherId) { $level = $item[$this->level]; } if ($withself) { if ($item[$this->cid] == $fatherId) { $result[] = $item; $level = $item[$this->level]; break; } } } if (!isset($level)) { return array(); } $this->depth = $depth; $this->startLevel = $level; $nextLevel = $withself ? ($level + 1) : $level; return array_merge($result,$this->getChildren($resArr,$fatherId,$nextLevel)); } /** * 取出某一分類下的全部ID,返回數組,fatherId = 0爲根目錄 * @param $fatherId 父類ID * @param $widthself 取子分類時,是否包含本身,默認不包含 * @param $depth 要讀取的層級深度,默認查出全部子分類 */ public function getAllCategoryId($fatherId = 0,$widthself = false,$depth = 0,$display = false) { $idArr = array(); if ($widthself) { array_push($idArr,$fatherId); } $cate = $this->getAllCategory($fatherId,$widthself,$depth,$display); foreach($cate as $item) { $idArr[] = $item[$this->cid]; } return $idArr; } /** * 用於在下拉列表框中使用 * @param $fatheriId 父類ID * @param $widthself 若取子分類的時候是否獲取自己 * @param $depth 分類深度 * @param $display 分類顯示狀態 * @param $selectId 用於編輯分類時自動設置默認狀態爲selected */ public function getOptionStr($fatherId = 0,$withself = false,$depth = 0,$display = false,$selectId = 0) { $str = ''; $cate = $this->getAllcategory($fatherId,$withself,$depth,$display); if (!empty($cate)) { $line = '┣'; foreach($cate as $item) { $selected = ''; if ($selectId != 0 && $item[$this->cid] == $selectId) { $selected = 'selected'; } $str .= '<option '.$selected.' value="'.$item[$this->cid].'">'.$line.str_repeat('━',($item[$this->level] - $this->startLevel)*2).$item[$this->cateName].'</option>'; } } return $str; } /** * 用於列表顯示,按ul li標籤組織 * @param $fatherId 父分類ID * @param $widthself 若取子分類的時候是否獲取自己 * @param $widthHref 是否提供超連接,即編輯和刪除連接 * @param $depth 分類深度 */ public function getListStr($fatherId = 0,$widthself = false,$withHref = true,$depth = 0,$display = false) { //開頭 $str = ''; $startLevel = -1; $preLevel = 0; $cate = $this->getAllCategory($fatherId,$widthself,$depth,$display); if (!empty($cate)) { foreach($cate as $item) { if ($startLevel < 0) { $startLevel = $item[$this->level]; } if ($item[$this->level] < $preLevel) { $str .='</li>'.str_repeat('</ul></li>',$preLevel - $item[$this->level]); } elseif ($item[$this->level] > $preLevel) { $str .='<ul>'; } else { $str .='</li>'; } if ($withHref && $item[$this->cid]!= 0) { $str .= '<li> <span style="float:right;"> '.($this->isDisplay($item[$this->cid]) ? "正常" : "待審").' <a href="'.site_url('cate/edit/'.$item[$this->cid]).'" class="mr50 ml200">edit</a> <a onclick=\'return confirm("Are your sure to delete?");\' href="'.site_url('cate/delete/'.$item[$this->cid]).'">del</a> </span> '.str_repeat(' ',($item[$this->level]-$this->startLevel)*4).' <span class="fb f16">'.($this->isChildren($item[$this->cid]) ? "+" : "-").'</span> <input type="text" name="cname" class="span2" value="'.$item[$this->cateName].'" style="border:0px;" />'; } else { $str .= '<li>'.$item[$this->cateName]; } $preLevel = $item[$this->level]; } } //收尾 $str .=str_repeat('</li></ul>',$preLevel - $startLevel + 1); return $str; } /** * 增長分類 * @param $fatherId 父類ID * @param $cateName 分類名稱 * @param $content 分類介紹 * @param $sort 分類排序, 只對同一級下的分類有用 * @param $display 分類顯示狀態 */ public function addCategory($fatherId,$cateName,$content,$sort,$display) { //先獲取父類的類別信息 $parentInfo = $this->fetchOne($fatherId); //p($parentInfo); //獲取分類的分類級別 if (isset($parentInfo[$this->level])) { $level = $parentInfo[$this->level]; } else { $level = 0; } $data = array( $this->fatherId => $fatherId, $this->cateName => $cateName, $this->content => $content, $this->sort => $sort, $this->level => $level + 1, $this->display => $display ); $this->CI->db->insert($this->tableName,$data); return $this->CI->db->affected_rows(); } /** * 刪除分類 * @param $cid 要刪除的分類ID * @param $widthChild 是否刪除下面的子分類,默認會刪除 */ public function delCategory($cid,$widthChild = true) { if ($widthChild) { $idArr = $this->getAllCategoryId($cid,true); $this->CI->db->where_in($this->cid,$idArr); } else { $this->CI->db->where($this->cid,$cid); } $this->CI->db->delete($this->tableName); return $this->CI->db->affected_rows(); } /** * 更新分類 * @param $cid 要編輯的分類ID * @param $fatherId 父類ID * @param $cateName 分類的名稱 * @param $sort 分類排序 * @param $display 分類顯示狀態 */ function editCategory($cid,$fatherId,$cateName,$content,$sort,$display) { //先獲取父分類的信息 $parentInfo = $this->fetchOne($fatherId); //獲取當前等級 if(isset($parentInfo[$this->level])) { $level = $parentInfo[$this->level]; } else { $level = 0; } $currentInfo = $this->fetchOne($cid); //p($currentInfo); $newLevel = $level + 1; $levelDiff = $newLevel - $currentInfo[$this->level]; //修改子分類的level if(0 != $levelDiff) { $childIdArr = $this->getAllCategoryId($cid); foreach($childIdArr as $item) { $this->CI->db->set($this->level, $this->level.'+'.$levelDiff, FALSE); $this->CI->db->where($this->cid, $item); $this->CI->db->update($this->tableName); } } //修改本身的信息 $data = array( $this->fatherId => $fatherId, $this->cateName => $cateName, $this->level => $newLevel, $this->sort => $sort, $this->display => $display, ); $this->CI->db->where($this->cid, $cid); $this->CI->db->update($this->tableName, $data); return $this->CI->db->affected_rows(); } /** * 按順序返回分類數組,用遞歸實現 * @param unknown_type $cateArr * @param unknown_type $fatherId * @param unknown_type $level */ private function getChildren($cateArr,$fatherId=0,$level = 1) { if($this->depth != 0 && ($level >=($this->depth + $this->startLevel))) { return array(); } $resultArr = array(); $childArr = array(); //遍歷當前父ID下的全部子分類 foreach($cateArr as $item) { if($item[$this->fatherId] == $fatherId && ($item[$this->level] == $level)) { //將子分類加入數組 $childArr[] = $item; } } if(count($childArr) == 0) { //不存在下一級,無需繼續 return array(); } //存在下一級,按sort排序先 usort($childArr,array('Category','compareBysort')); foreach($childArr as $item) { $resultArr[] = $item; $temp = $this->getChildren($cateArr,$item[$this->cid],($item[$this->level] + 1)); if(!empty($temp)) { $resultArr = array_merge($resultArr, $temp); } } return $resultArr; } //比較函數,提供usort函數用 private function compareBysort($a, $b) { if ($a == $b) { return 0; } return ($a[$this->sort] > $b[$this->sort]) ? +1 : -1; } //判斷是否有子類別 function isChildren($id) { //從數據庫中取出只有fatherId字段的數據,返回數組 $this->CI->db->select($this->fatherId); $query = $this->CI->db->get($this->tableName); $resArr = $query->result_array(); foreach ($resArr as $v) { $arr[] = $v[$this->fatherId]; } return (in_array($id,array_unique($arr))) ? true : false; } //判斷狀態是否啓用 function isDisplay($id) { $query = $this->fetchOne($id); return ($query[$this->display] == 1) ? true : false; } }四、視圖 (源碼在 application/views 文件夾)
分類顯示視圖:
sql
<html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Cate_index</title> <link rel="stylesheet" href="<?php echo $base_url; ?>/bootstrap/css/bootstrap.min.css" type="text/css" media="screen" charset="utf-8"> <link rel="stylesheet" href="<?php echo $base_url; ?>/public/css/base.css" type="text/css" media="screen" charset="utf-8"> </head> <body> <div class="w700 bc mt50"> <h1 class="fb f20 mb20">分類列表顯示</h1> <?php echo $tree_str ?> </div> </body> </html>分類添加和編輯視圖:
<html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Cate_edit</title> <link rel="stylesheet" href="<?php echo $base_url; ?>/bootstrap/css/bootstrap.min.css" type="text/css" media="screen" charset="utf-8"> <link rel="stylesheet" href="<?php echo $base_url; ?>/public/css/base.css" type="text/css" media="screen" charset="utf-8"> </head> <body> <?php echo form_open((($cid = $this->uri->segment(3)) === FALSE) ? 'cate/insert' : 'cate/update');?> <?php echo form_hidden('cid', ($cid === FALSE ? '' : $this->uri->segment(3))); ?> <table class="table table-bordered w500 mt50 bc"> <tr> <td width='25%'>選擇父分類:</td> <td> <select name='fatherId'><?php echo $option_str; ?></select> </td> </tr> <tr> <td>分類名稱:</td> <td><?php echo form_input('cateName',($cid === FALSE) ? '' : $post['cateName']); ?></td> </tr> <tr> <td>分類介紹:</td> <td><?php echo form_textarea('content',($cid === FALSE) ? '' : $post['content']); ?></td> </tr> <tr> <td>分類排序:</td> <td><?php echo form_input('sort',($cid === FALSE) ? '' : $post['sort'],'class="span1"'); ?></td> </tr> <tr> <td>是否啓用:</td> <td> <?php echo form_checkbox("display",'1',($cid === FALSE ? '' : ($post['display']==='1' ? TRUE : FALSE))) ;?> </td> </tr> <tr> <td colspan='2' class="form-actions"> <?php echo form_submit("submit","提交","class='btn btn-primary'"); ?> <?php echo form_reset("reset","重置","class='btn'"); ?> </td> </tr> </table> <?php echo form_close(); ?> </body> </html>五、應用
(4)、瀏覽器輸入http://localhost/CI_cate/index.php/cate/index便可訪問分類顯示頁 ,輸入http://localhost/CI_cate/index.php/cate/edit便可訪問添加分類頁。 數據庫
附件下載:http://bbs.lampbrother.net/job.php?action=download&aid=22124