• 前序遍历树算法实现无限级分类


    分类的话一般用的都是无限极分类,无限极分类的有点是灵活,容易插入,但是在分类量特别大的情况下,使用前序遍历树算法代替无限极分类更好,因为当分类特别多的时候无限极分类的查询是每次都要查询所有,所以前序遍历树算法在此方面的能更好的。当然如果分类涉及经常变更,更改。无限极分类还是有他的有点。在此,分享一个自己的实现类。

    <?php
    /**
    * 前序遍历树算法实现无限极分类
    * @author zaizai
    * @link http://www.tuhuokeji.com
    */
    class Category
    {
    private $tablename = null;
    public function __construct($tablename)
    {
    if(is_null($this->$tablename)){
    $this->tablename = $tablename;
    }
    }
    /**
    * 设置表名
    * @Author   zaizai
    * @DateTime 2016-04-02T11:31:39+0800
    * @param    string                   $tablename [description]
    */
    public function setTbale(string $tablename)
    {
    return $this->tablename = $tablename;
    }
    public function getTable()
    {
    return $this->tablename;
    }
    /**
    * 显示树状结构
    * @Author   zaizai
    * @DateTime 2016-04-02T11:33:33+0800
    * @return   [type]                   [description]
    */
    public function view($pageindex,$pagesize,$where = '')
    {            
    $total = pdo_fetchcolumn('select count(id) from '.tablename($this->tablename).' where id!=1');
    $list = pdo_fetchAll('select * from '.tablename($this->tablename).$where.' order by lft asc  limit ' . ($pageindex - 1) * $pagesize . ',' . $pagesize);
    $pager = pagination($total, $pageindex, $pagesize);
    //两个循环而已,没有递归
    $parent = array();
    $arr_list = array();
    foreach($list as $item){
    if(count($parent)){
    while (count($parent) -1 > 0 && $parent[count($parent) -1]['rgt'] < $item['rgt']){
    array_pop($parent);
    }
    }
    $item['depath'] = count($parent);
    $parent[]  = $item;
    $arr_list[]= $item;
    }
    //显示树状结构
    foreach($arr_list as $k=> $a)
    {
    if($a['id'] != 1 ){
    if($a['depath'] !=1){
    $arr_list[$k]['view'] = str_repeat("&nbsp;&nbsp;&nbsp;&nbsp;", $a['depath']).'|---';
    }
    }else{
    unset($arr_list[$k]);
    }
    }
    return array('list'=>$arr_list,'pager'=>$pager);
    }
    /**
    * 插入操作很简单找到其父节点,之后把左值和右值大于父节点左值的节点的左右值加上2,之后再插入本节点,左右值分别为父节点左值加一和加二
    * @Author   zaizai
    * @DateTime 2016-04-02T11:34:01+0800
    * @param    [type]                   $parent_id [description]
    * @param    [type]                   $data      [description]
    */
    public function add($parent_id,$data)
    {
    $parent_id = empty($parent_id)?1:$parent_id;
    //获取到父级分类的lft rgt
    $parent_category = pdo_get($this->tablename,array('id'=>$parent_id),array('lft','rgt','id'));
    // 1.左值和右值大于父节点左值的节点的左右值加上2
    if(!empty($parent_category)){
    pdo_query('update '.tablename($this->tablename).' set lft=lft+2 where lft >'.$parent_category['lft']);
    pdo_query('update '.tablename($this->tablename).' set rgt=rgt+2 where rgt >'.$parent_category['lft']);
    }
    $data = array_merge(array('lft'=>$parent_category['lft']+1,'rgt'=>$parent_category['lft']+2),$data);
    return pdo_insert($this->tablename,$data);
    }
    /**
    * 删除
    * 
    * #1.得到删除的节点,将右值减去左值然后加1,得到值$width = $rgt - $lft + 1;
    * #2.删除左右值之间的所有节点
    * #3.修改条件为大于本节点右值的所有节点,操作为把他们的左右值都减去$width
    * @Author   zaizai
    * @DateTime 2016-04-02T11:36:44+0800
    * @param    int                   $id 删除的节点id
    * @return   bool                       返回值
    */
    public function delete($id)
    {
    //通过分类id获取分类
    $category = pdo_get($this->tablename,array('id'=>$id),array('id','lft','rgt'));
    //计算$width
    $width = $category['rgt'] - $category['lft'] + 1;
    // 1.删除该条分类
    $res = pdo_delete($this->tablename,array('id'=>$id));
    // 2.删除左右值之间的所有分类
    pdo_query('delete from '.tablename($this->tablename).' where lft>:lft and lft<:rgt and id!=1',array(':lft'=>$category['lft'],':rgt'=>$category['rgt']));
    // 3.修改其它节点的值        
    $res1 = pdo_update($this->tablename,array('lft'=>"lft-{$width}"),array('lft'=>$category['rgt']));
    $res2 = pdo_update($this->tablename,array('rgt'=>"rgt-{$width}"),array('rgt'=>$category['rgt']));
    return $res;
    }
    /**
    * 编辑节点
    * @Author   zaizai
    * @DateTime 2016-04-02T11:34:58+0800
    * @param    int                   $id   节点名称
    * @param    array                   $data 入库的数据
    * @return   bool                         返回值
    */
    public function edit($id,$data)
    {
    //不用说了, 直接通过id编辑
    return pdo_update($this->tablename,$data,array('id'=>$id));
    }
    //获取子孙
    public function getSons($id)
    {
    $item = pdo_fetch('select * from '.tablename($this->tablename).' where id=:id',array(':id'=>$id));
    if($item){
    $sql = 'SELECT `id`,`title`,`lft`,`rgt` FROM '.tablename($this->tablename).' WHERE `lft`>='.$item['lft'].' AND `rgt`<='.$item['rgt'];
    return pdo_fetchAll($sql);
    }
    return false;
    }
    /**
    * 获取子类的直接父类
    * @Author   zaizai
    * @DateTime 2016-05-03T11:00:43+0800
    * @param    int                   $sonid    子类的id  
    * @return   array|false                          直接父类
    */
    public function getParent($sonid)
    {
    $item = pdo_fetch('select * from '.tablename($this->tablename).' where id=:id',array(':id'=>$sonid));
    if($item){
    $sql = 'SELECT `id`,`title`,`lft`,`rgt` FROM '.tablename($this->tablename).' WHERE `lft`<'.$item['lft'].' AND `rgt`>'.$item['rgt'].' order by rgt asc limit 1';
    return pdo_fetch($sql);
    }
    return false;
    }
    /**
    * 获取所有的子类
    * @Author   zaizai
    * @DateTime 2016-05-03T11:00:05+0800
    * @param    int                   $sonid 子类的id
    * @return   array                          所有的父类
    */
    public function getParents($sonid)
    {
    $item = pdo_fetch('select * from '.tablename($this->tablename).' where id=:id',array(':id'=>$sonid));
    if($item){
    $sql = 'SELECT `id`,`title`,`lft`,`rgt` FROM '.tablename($this->tablename).' WHERE `lft`<'.$item['lft'].' AND `rgt`>'.$item['rgt'];
    return pdo_fetchAll($sql);
    }
    return false;
    }
    /**
    * 取出第几级
    * @Author   zaizai
    * @DateTime 2016-05-13T18:07:09+0800
    * @param    [type]                   $depath 层级
    * @return   [type]                           [description]
    */
    public function get_Paret($depath = 1)
    {
    $list = pdo_fetchAll('select * from '.tablename($this->tablename) .' where status=:status  order by lft asc',array(':status'=>0));
    //两个循环而已,没有递归
    $parent = array();
    $arr_list = array();
    foreach($list as $k => $item){
    if(count($parent)){
    while (count($parent) -1 > 0 && $parent[count($parent) -1]['rgt'] < $item['rgt']){
    array_pop($parent);
    }
    }
    $item['depath'] = count($parent);
    $parent[]  = $item;
    $arr_list[]= $item;
    if($item['id'] != 1 ){
    if($item['depath'] == $depath){
    $aa[] = $item;
    //按照sort排序
    foreach ($aa as $key => $row)
    {
    $vals[$key] = $row['sort'];
    }
    array_multisort($vals, SORT_ASC, $aa);
    }
    }else{
    unset($list[$k]);
    }         
    }
    return $aa;
    }
    /**
    * 取出某父级的第几级子级
    * @Author   zaizai
    * @DateTime 2016-05-13T18:07:09+0800
    * @param    [type]                   $depath 层级
    * @return   [type]                           [description]
    */
    public function get_sons_level($id,$depath = 1)
    {
    $abc = pdo_fetch('select * from '.tablename($this->tablename).' where id=:id',array(':id'=>$id));
    if($abc){
    $list = pdo_fetchAll('select * from '.tablename($this->tablename).' WHERE `lft`>='.$abc['lft'].' AND `rgt`<='.$abc['rgt'] .' order by lft asc');
    }
    //两个循环而已,没有递归
    $parent = array();
    $arr_list = array();
    foreach($list as $k => $item){
    if(count($parent)){
    while (count($parent) -1 > 0 && $parent[count($parent) -1]['rgt'] < $item['rgt']){
    array_pop($parent);
    }
    }
    $item['depath'] = count($parent);
    $parent[]  = $item;
    $arr_list[]= $item;
    if($item['id'] != 1 ){
    if($item['depath'] == $depath){
    $aa[] = $item;
    //按照sort排序
    foreach ($aa as $key => $row)
    {
    $vals[$key] = $row['sort'];
    }
    array_multisort($vals, SORT_ASC, $aa);
    }
    }else{
    unset($list[$k]);
    }
    }
    return $aa;
    }
    //测试排序
    public function test_sort($where=''){
    foreach ($this->get_Paret(1) as $v){   //PHP<5.5   用这个
    $parentid[]=$v['id'];
    }
    for ($i=0;$i<count($parentid);$i++){
    $sons[$parentid[$i]]= ($this->get_sons_level($parentid[$i],1));
    }
    foreach ($sons as $k=>$v){
    $sons[$parentid[$k]]=$v[$k];
    }
    foreach ($this->get_Paret(1) as $k=>$v){   //PHP<5.5   用这个
    $parent[]=$v;
    }
    foreach ($this->get_Paret(2) as $v){   //PHP<5.5   用这个
    $sonsid[]=$v['id'];
    }
    for ($i=0;$i<count($sonsid);$i++){
    $sun[$sonsid[$i]]= ($this->get_sons_level($sonsid[$i],1));
    }
    foreach ($sun as $k=>$v){
    $sun[$sonsid[$k]]=$v[$k];
    }
    return  $this->name($parent,$sons,$sun);
    }
    public function name($a,$b,$c)
    {
    $list = array();
    $list[] = $a;
    $list[] = $b;
    $list[] = $c;
    return $list;
    }
    }
  • 相关阅读:
    将jetty嵌入到应用中的简单案例
    修改jetty的默认端口号
    Linux下安装jetty服务器
    影视-纪录片:《超级装备》
    影视-纪录片:《飞向月球》
    影视-电视剧:《罪域》
    影视-电视剧:《黎明之前》
    影视-电视剧:《人民的名义》
    几何:不可能图形
    几何:悖理图形
  • 原文地址:https://www.cnblogs.com/gyrgyr/p/6806743.html
Copyright © 2020-2023  润新知