/**
应用基于thinkphp的左右值无限分类
**/
class Category
{
//传入实化的对象【M('表名')】
private $objCategory;
//基础节点ID号
public $intCurrentId;
//设置制表符样式
private $arrTabsStyle = array(
'indent' => ' ',
'process' => '├ ',
'end'=>'└ '
);
//构造函数初始化
public function __construct($objCategory)
{
$this->objCategory = $objCategory;
}
//验证传入ID【大于0的数字】
private function checkFun($intId)
{
//$intId优先验证
if(isset($intId))
{
$this->intCurrentId = $intId;
return true;
}
//如果$this->intCurrentId 已设置,验证
else
{
if(isset($this->intCurrentId))
{
return true;
}
else
{
return false;
}
}
}
//根据ID号获取当前节点左右值
private function setCurrentData($intId)
{
if(false == $this->checkFun($intId))
{
return false;
}
$map['id'] = $this->intCurrentId;
return $this->objCategory->field(array('lft','rgt'))->where($map)->find();
}
/*
*作用:
设置输出列表数据的制表符样式
*参数:
$key:arrTabsStyle的KEY
$value:arrTabsStyle的值
*/
public function setTabStyle($key, $value = '')
{
if(isset($this->arrTabsStyle[$key]))
{
$this->arrTabsStyle[$key] = $value;
}
}
/*
*作用:
根据ID号获取当前节点数据
*参数:
$intId:可设置的,需读取节点ID号
*/
public function getCurrentData($intId)
{
if(false == $this->checkFun($intId))
{
return false;
}
$map['id'] = $this->intCurrentId;
return $this->objCategory->field(array('id','title'))->where($map)->find();
}
/*
*作用:
获取当前节点的父节点数据
*参数:
$intId:需要读取节点的ID
*/
public function getParentCategoryData($intId)
{
$arrRoot = $this->setCurrentData($intId);
if($arrRoot)
{
$map['lft'] = array('LT', $arrRoot['lft']);
$map['rgt'] = array('GT', $arrRoot['rgt']);
return $this->objCategory->where($map)->find();
}
else
{
return false;
}
}
/*
*作用:
获取ID下节点列表
*参数:
$intId:需要读取节点的父ID
$intLevel:目录等级默认到100级
*/
public function getCategoryList($intId = 1, $intLevel = 100)
{
//获取选定节点左右值,得出取值区间
$arrRoot = $this->setCurrentData($intId);
if($arrRoot)
{
//读取数据库符合条件的数据
$map['lft'] = array('BETWEEN', array($arrRoot['lft'], $arrRoot['rgt']));
$arrChildList = $this->objCategory->where($map)->order('lft')->select();
//return $arrChildList;
//对取出数据进行格式化
$arrRight = array();
foreach($arrChildList as $v)
{
if(count($arrRight))
{
while ($arrRight[count($arrRight) - 1] <$v[&#039;rgt&#039;])
{
array_pop($arrRight);
}
}
//设置读取目录等级
if($intLevel > count($arrRight))
{
$title = $v[&#039;title&#039;];
//设置输出时的样式
if(count($arrRight))
{
$title = $this->arrTabsStyle[&#039;process&#039;].$title;
}
$title = str_repeat($this->arrTabsStyle[&#039;indent&#039;], count($arrRight)).$title;
$returnCategoryList[] = array(&#039;id&#039;=>$v[&#039;id&#039;],&#039;title&#039;=>$title,&#039;lft&#039;=>$v[&#039;lft&#039;],&#039;rgt&#039;=>$v[&#039;rgt&#039;]);
$arrRight[] = $v[&#039;rgt&#039;];
}
}
return $returnCategoryList;
}
return false;
}
/*
*作用:
获取节点的子节点数
*参数:
$intId:需要读取节点的父ID
*/
public function getCategoryCount($intId)
{
$arrRoot = $this->setCurrentData($intId);
return ($arrRoot[&#039;rgt&#039;] - $arrRoot[&#039;lft&#039;] - 1) / 2;
}
/*
*作用:
添加节点
*参数:
$bolType:true添加到节点前面,false添加到节点尾部
$intId:添加到的父节点
*/
public function insertCategory($bolType = false, $intPid)
{
$data = I(&#039;param.&#039;);
if(!isset($intPid))
{
$intPid = $data[&#039;pid&#039;];
}
$arrRoot = $this->setCurrentData($intPid);
if($arrRoot)
{
if($bolType)
//true添加到节点前面
{
$this->objCategory->where(&#039;rgt>&#039;.$arrRoot[&#039;lft&#039;])->setInc(&#039;rgt&#039;,2);
$this->objCategory->where(&#039;lft>&#039;.$arrRoot[&#039;lft&#039;])->setInc(&#039;lft&#039;,2);
//设置当前节点的左右值
$data[&#039;lft&#039;] = $arrRoot[&#039;lft&#039;] + 1;
$data[&#039;rgt&#039;] = $arrRoot[&#039;lft&#039;] + 2;
}
else
//false添加到节点尾部
{
$this->objCategory->where(&#039;rgt>=&#039;.$arrRoot[&#039;rgt&#039;])->setInc(&#039;rgt&#039;,2);
$this->objCategory->where(&#039;lft>&#039;.$arrRoot[&#039;rgt&#039;])->setInc(&#039;lft&#039;,2);
$data[&#039;lft&#039;] = $arrRoot[&#039;rgt&#039;];
$data[&#039;rgt&#039;] = $arrRoot[&#039;rgt&#039;] + 1;
}
return $this->objCategory->add($data);
}
else
{
return false;
}
}
/*
*作用:
删除节点
*参数:
$intId:被删除的节点ID
*/
public function deleteCategory($intId)
{
$arrRoot = $this->setCurrentData($intId);
if($arrRoot)
{
$ints = $arrRoot[&#039;rgt&#039;] - $arrRoot[&#039;lft&#039;] + 1;
$map[&#039;lft&#039;] = array(&#039;BETWEEN&#039;, array($arrRoot[&#039;lft&#039;], $arrRoot[&#039;rgt&#039;]));
$this->objCategory->where($map)->delete();
$this->objCategory->where(&#039;lft>&#039;.$arrRoot[&#039;rgt&#039;])->setDec(&#039;lft&#039;,$ints);
$this->objCategory->where(&#039;rgt>&#039;.$arrRoot[&#039;rgt&#039;])->setDec(&#039;rgt&#039;,$ints);
return true;
}
else
{
return false;
}
}
/*
*作用:
更新节点
*参数:
$intId:被删除的节点ID
*/
public function updateCategory()
{
//读取POST数据存入数组
$data = I(&#039;param.&#039;);
//父ID等于子ID,直接跳出
if($data[&#039;pid&#039;] == $data[&#039;id&#039;]){return false;}
//post.pid和当前父post.old相等说明未改变目录,不更新左右值
if($data[&#039;pid&#039;] !== $data[&#039;oldpid&#039;])
{
/**********************************【读取所需的相关值】********************************/
//获取新的父节点的数据
$arrParent = $this->setCurrentData($data[&#039;pid&#039;]);
//取当前节点的数据
$arrCurrent = $this->setCurrentData($data[&#039;id&#039;]);
/* 任务:删除节点 */
/**********************************【A-1:隔离数据】************************************/
//将需要调整位置的左右值+100000
$map[&#039;lft&#039;] = array(
array(&#039;EGT&#039;, $arrCurrent[&#039;lft&#039;]),
array(&#039;ELT&#039;, $arrCurrent[&#039;rgt&#039;])
);
$this->objCategory->where($map)->setInc(&#039;lft&#039;,100000);
//因为左值已更新,所以条件变化+100000
$map[&#039;lft&#039;] = array(
array(&#039;EGT&#039;, $arrCurrent[&#039;lft&#039;] + 100000),
array(&#039;ELT&#039;, $arrCurrent[&#039;rgt&#039;] + 100000)
);
$this->objCategory->where($map)->setInc(&#039;rgt&#039;,100000);
unset($map);
/**********************************【A-2:更新正常节点值】******************************/
//获取隔离节点后续更新的步长值
$intStep = $arrCurrent[&#039;rgt&#039;] - $arrCurrent[&#039;lft&#039;] + 1;
//更新节点左右值
$map[&#039;lft&#039;] = array(
array(&#039;GT&#039;, $arrCurrent[&#039;rgt&#039;]),
array(&#039;LT&#039;, 100000)
);
$this->objCategory->where($map)->setDec(&#039;lft&#039;,$intStep);
unset($map);
$map[&#039;rgt&#039;] = array(
array(&#039;GT&#039;, $arrCurrent[&#039;rgt&#039;]),
array(&#039;LT&#039;, 100000)
);
$this->objCategory->where($map)->setDec(&#039;rgt&#039;,$intStep);
unset($map);
/* 完成:删除节点 */
/* 任务:更新节点 */
/**********************************【B-1:新父节目点提供下级节点的空间】****************/
$map[&#039;lft&#039;] = array(
array(&#039;GT&#039;, $arrParent[&#039;lft&#039;]),
array(&#039;LT&#039;, 100000)
);
$this->objCategory->where($map)->setInc(&#039;lft&#039;,$intStep);
unset($map);
$map[&#039;rgt&#039;] = array(
array(&#039;GT&#039;, $arrParent[&#039;lft&#039;]),
array(&#039;LT&#039;, 100000)
);
$this->objCategory->where($map)->setInc(&#039;rgt&#039;,$intStep);
unset($map);
/**********************************【B-2:将节点放入指定下级的空间】********************/
//获取隔离节点后续更新的步长值
$intStep = 100000 + ($arrCurrent[&#039;lft&#039;] - ($arrParent[&#039;lft&#039;] + 1));
//更新左右值大于父节点左值的节点的左右值
$map[&#039;lft&#039;] = array(
array(&#039;EGT&#039;, $arrCurrent[&#039;lft&#039;] + 100000),
array(&#039;ELT&#039;, $arrCurrent[&#039;rgt&#039;] + 100000)
);
$this->objCategory->where($map)->setDec(&#039;lft&#039;,$intStep);
unset($map);
$map[&#039;rgt&#039;] = array(
array(&#039;EGT&#039;, $arrCurrent[&#039;lft&#039;] + 100000),
array(&#039;ELT&#039;, $arrCurrent[&#039;rgt&#039;] + 100000)
);
$this->objCategory->where($map)->setDec(&#039;rgt&#039;,$intStep);
}
return $this->objCategory->where(&#039;id=&#039;.$data[&#039;id&#039;])->setField(&#039;title&#039;, $data[&#039;title&#039;]);
}
}
?>
使用:
class CategoryAction extends CommonAction {
private $objCG;
public function _initialize(){
//导入分类库
import(&#039;@.ORG.Util.Category&#039;);
$this->objCG = new Category(M(&#039;CommonCategory&#039;));
}
//目录列表
public function index($id = 1){
$this->cateorylist = $this->objCG->getCategoryList($id);
$this->display();
}
//添加目录
public function add($id=1){
$this->cateorylist = $this->objCG->getCategoryList($id);
$this->display();
}
//编辑目录
public function edit($id){
if (!empty($id)){
//输出所有的节点
$this->cateorylist = $this->objCG->getCategoryList(1);
//读取当前节点数据
$vo = $this->objCG->getCurrentData($id);
if ($vo){
//读取当前节点的父节点数据
$arrParent = $this->objCG->getParentCategoryData($id);
$vo[&#039;pid&#039;] = $arrParent[&#039;id&#039;];
$this->assign(&#039;vo&#039;,$vo);
$this->display();
}else{
$this->error(&#039;数据不存在!&#039;);
}
}else{
$this->error(&#039;数据不存在!&#039;);
}
}
//添加目录:操作
public function insert(){
$list = $this->objCG->insertCategory();
if ($list !== false)
{
$this->success(&#039;数据保存成功!&#039;);
}
else
{
$this->error(&#039;数据写入错误!&#039;);
}
}
public function delete($id){
if (!empty($id))
{
$result = $this->objCG->deleteCategory($id);
if ($result)
{
$this->success(&#039;删除成功!&#039;);
}
else
{
$this->error(&#039;删除出错!&#039;);
}
}
else
{
$this->error(&#039;ID错误!&#039;);
}
}
public function update(){
$list = $this->objCG->updateCategory();
if ($list !== false)
{
$this->success(&#039;更新成功!&#039;);
}
else
{
$this->error("操作失败!");
}
}
}
AD:真正免费,域名+虚机+企业邮箱=0元