zoukankan      html  css  js  c++  java
  • php 实现无限极分类

    原始数据

    $array = array(
        array('id' => 1, 'pid' => 0, 'n' => '河北省'),
        array('id' => 2, 'pid' => 0, 'n' => '北京市'),
        array('id' => 3, 'pid' => 1, 'n' => '邯郸市'),
        array('id' => 4, 'pid' => 2, 'n' => '朝阳区'),
        array('id' => 5, 'pid' => 2, 'n' => '通州区'),
        array('id' => 6, 'pid' => 4, 'n' => '望京'),
        array('id' => 7, 'pid' => 4, 'n' => '酒仙桥'),
        array('id' => 8, 'pid' => 3, 'n' => '永年区'),
        array('id' => 9, 'pid' => 1, 'n' => '武安市'),
        array('id' => 10, 'pid' => 8, 'n' => '永年区镇'),
        array('id' => 11, 'pid' => 0, 'n' => '上海市')
    );

    生成无限极分类

    /** 所有的分类
     * @parem $array 数组
     * @parem $pid ,最高级别,默认为0,输出从pid 级别的数据
     * @parem $level 层级,默认0
     * */
    function getTree($array, $pid =0, $level = 0){
    
        $f_name=__FUNCTION__; // 定义当前函数名
    
        //声明静态数组,避免递归调用时,多次声明导致数组覆盖
        static $list = [];
    
        foreach ($array as $key => $value){
            //第一次遍历,找到父节点为根节点的节点 也就是pid=0的节点
            if ($value['pid'] == $pid){
                //父节点为根节点的节点,级别为0,也就是第一级
                $flg = str_repeat('|--',$level);
                // 更新 名称值
                $value['n'] = $flg.$value['n'];
                // 输出 名称
                echo $value['n']."<br/>";
                //把数组放到list中
                $list[] = $value;
                //把这个节点从数组中移除,减少后续递归消耗
                unset($array[$key]);
                //开始递归,查找父ID为该节点ID的节点,级别则为原级别+1
                $f_name($array, $value['id'], $level+1);
            }
        }
        return $list;
    }
    // 调用
    $list=getTree($array);

    调用结果:

    河北省
    |--邯郸市
    |--|--永年区
    |--|--|--永年区镇
    |--武安市
    北京市
    |--朝阳区
    |--|--望京
    |--|--酒仙桥
    |--通州区

    嵌套标签,前端可以(通过选取子节点)全选、取消全选

    function getTree($array, $pid =0, $level = 0){
    
        $f_name=__FUNCTION__; // 定义当前函数名
    
        // 空数组 不在执行
        if(empty($array))
            return;
    
        //声明静态数组,避免递归调用时,多次声明导致数组覆盖
        static $html;
        $html.="<ul>";
        
        foreach ($array as $key => $value){
    
            //第一次遍历,找到父节点为根节点的节点 也就是pid=0的节点
            if ($value['pid'] == $pid){
                //父节点为根节点的节点,级别为0,也就是第一级
                $flg = str_repeat('|--',$level);
                // 更新 名称值
                $value['n'] = $flg.$value['n'];
                $html.=$temp="<li><input type="checkbox" name="limit_id[]" value='".$value['id']."' >".$value['n'];
    
                //把这个节点从数组中移除,减少后续递归消耗
                unset($array[$key]);
                //开始递归,查找父ID为该节点ID的节点,级别则为原级别+1
                $vv=$f_name($array, $value['id'], $level+1);
    
                // 如果顶级分类下没有一个下级,删除此分类,此步骤可以省略
                if(empty($vv) && ($pid<1))
                {
                    $html=str_replace($temp,'',$html);
                }
                $html.="</li>
    ";
    
            }
        }
        $html.="</ul>
    ";
    
        // 删除多余的 ul 标签
        $html=str_replace("<ul></ul>",'',$html);
        return $html;
    }

    html 输出结果

    <ul>
        <li><input type="checkbox" name="limit_id[]" value='1'>河北省
            <ul>
                <li><input type="checkbox" name="limit_id[]" value='3'>|--邯郸市
                    <ul>
                        <li><input type="checkbox" name="limit_id[]" value='8'>|--|--永年区
                            <ul>
                                <li><input type="checkbox" name="limit_id[]" value='10'>|--|--|--永年区镇
                                </li>
                            </ul>
                        </li>
                    </ul>
                </li>
                <li><input type="checkbox" name="limit_id[]" value='9'>|--武安市
                </li>
            </ul>
        </li>
        <li><input type="checkbox" name="limit_id[]" value='2'>北京市
            <ul>
                <li><input type="checkbox" name="limit_id[]" value='4'>|--朝阳区
                    <ul>
                        <li><input type="checkbox" name="limit_id[]" value='6'>|--|--望京
                        </li>
                        <li><input type="checkbox" name="limit_id[]" value='7'>|--|--酒仙桥
                        </li>
                    </ul>
                </li>
                <li><input type="checkbox" name="limit_id[]" value='5'>|--通州区
                </li>
            </ul>
        </li>
        </li>
    </ul>
    View Code 

    jquery 操作全选

    //父级选中 自动选中子级,同时选中自己的父级
        $('input[type="checkbox"]').change(function(e) {
            var checked = $(this).prop("checked"),
                container = $(this).parent(),
                siblings = container.siblings();
    
            container.find('input[type="checkbox"]').prop({
                indeterminate: false,
                checked: checked
            });
    
            function checkSiblings(el) {
    
                var parent = el.parent().parent(),
                    all = true;
    
                el.siblings().each(function() {
                    return all = ($(this).children('input[type="checkbox"]').prop("checked") === checked);
                });
    
                if (all && checked) {
    
                    parent.children('input[type="checkbox"]').prop({
                        indeterminate: false,
                        checked: checked
                    });
    
                    checkSiblings(parent);
    
                } else if (all && !checked) {
    
                    parent.children('input[type="checkbox"]').prop("checked", checked);
                    parent.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0));
                    checkSiblings(parent);
    
                } else {
    
                    el.parents("li").children('input[type="checkbox"]').prop({
                        indeterminate: true,
                        checked: false
                    });
    
                }
    
            }
            checkSiblings(container);
        });
        // 父级选中 自动选中子级
        /*$("input[type=checkbox]").each(function (i,ele){
            let _this=$(this);
            _this.click(function(){
                if(_this.prop('checked')==true)
                {
                    _this.parent().find('ul input').prop('checked',true);
                }else
                {
                    _this.parent().find('ul input').prop('checked',false);
                }
            });
        });*/

    数组嵌套

    引用嵌套,php变量默认的传值方式是按指传递,也就是说 假如说 遍历顺序是 河北省 邯郸市 当遍历到河北省时需要把河北省放到tree中,遍历到邯郸市时,需要把邯郸市放到河北省的子节点数组中,所以这里用到了引用传递,当你对河北省做更改时,tree数组中的河北省也一并做了更改

    function getTree($list, $pid = 0)
    {
        $tree = [];
        if (!empty($list)) {
            $newList = [];
    
            foreach ($list as $k => $v) {
                $newList[$v['id']] = $v;
            }
            foreach ($newList as $value ) {
                if ($pid == $value['pid']) {
                    $tree[] = &$newList[$value['id']];
                } elseif (isset($newList[$value['pid']]))
                {
                    $newList[$value['pid']]['items'][] = &$newList[$value['id']];
                }
            }
            // 如果顶级分类下没有一个下级,删除此分类,此步骤可以省略
            foreach ($tree as $k=>$v)
            {
                if(!isset($v['items']) && ($pid<1))
                    unset($tree[$k]);
            }
        }
        return $tree;
    }
    // 调用
    $list=getTree($array);
    var_dump($list);

    显示结果

    array(2) {
      [0]=>
      array(4) {
        ["id"]=>
        int(1)
        ["pid"]=>
        int(0)
        ["n"]=>
        string(9) "河北省"
        ["items"]=>
        array(2) {
          [0]=>
          array(4) {
            ["id"]=>
            int(3)
            ["pid"]=>
            int(1)
            ["n"]=>
            string(9) "邯郸市"
            ["items"]=>
            array(1) {
              [0]=>
              array(4) {
                ["id"]=>
                int(8)
                ["pid"]=>
                int(3)
                ["n"]=>
                string(9) "永年区"
                ["items"]=>
                array(1) {
                  [0]=>
                  array(3) {
                    ["id"]=>
                    int(10)
                    ["pid"]=>
                    int(8)
                    ["n"]=>
                    string(12) "永年区镇"
                  }
                }
              }
            }
          }
          [1]=>
          array(3) {
            ["id"]=>
            int(9)
            ["pid"]=>
            int(1)
            ["n"]=>
            string(9) "武安市"
          }
        }
      }
      [1]=>
      array(4) {
        ["id"]=>
        int(2)
        ["pid"]=>
        int(0)
        ["n"]=>
        string(9) "北京市"
        ["items"]=>
        array(2) {
          [0]=>
          array(4) {
            ["id"]=>
            int(4)
            ["pid"]=>
            int(2)
            ["n"]=>
            string(9) "朝阳区"
            ["items"]=>
            array(2) {
              [0]=>
              array(3) {
                ["id"]=>
                int(6)
                ["pid"]=>
                int(4)
                ["n"]=>
                string(6) "望京"
              }
              [1]=>
              array(3) {
                ["id"]=>
                int(7)
                ["pid"]=>
                int(4)
                ["n"]=>
                string(9) "酒仙桥"
              }
            }
          }
          [1]=>
          array(3) {
            ["id"]=>
            int(5)
            ["pid"]=>
            int(2)
            ["n"]=>
            string(9) "通州区"
          }
        }
      }
    }
    View Code

    根据子类id查找出所有父级分类信息

    /**根据指定id 的查询,所有的父节点
     * @parem $id_pid 要查询的id 或者 要查询id的pid;如果传入的是id 包括当前id 值,如果传入id_pid不包括当前id的值
     * @parem $array 查分类的数据,在项目使用中此参数可以不传,直接使用sql 查询
     * @parem $level 当前id所在层级,默认2
     * */
    function getParent($id_pid,$array=array(), $level = 2)
    {
        $f_name=__FUNCTION__; // 定义当前函数名
        static $list=array();
        //$array=Db::table('table_name')->where('id',$id_pid)->select(); TP5
        foreach($array as $k=>$v)
        {
            if($v['id']== $id_pid)
            {   //父级分类id等于所查找的id
                $flg = str_repeat('|--',$level);
                // 更新 名称值
                $v['n'] = $flg.$v['n'];
                // 输出 名称
                echo $v['n']."<br/>";
                $list[]=$v;
           // 删除数组
           unset($array[$k]);
    if($v['pid']>=0) { $f_name($v['pid'],$array,$level-1); } } } return $list; } // 调用 getParent(10,$array, $level = 3); echo "<hr/>"; getParent(8,$array, $level = 3);

    调用结果显示

    getParent(10,$array, $level = 3);
    |--|--|--永年区镇
    |--|--永年区
    |--邯郸市
    -----------------------------------------
    getParent(8,$array, $level = 3);
    河北省
    |--|--|--永年区
    |--|--邯郸市
    |--河北省

    根据父id获得所有下级子类数

    /**根据指定id 查询,所有的子节 
    * @parem $id 要查询的id 
    * @parem $array 查分类的数据,在项目使用中此参数可以不传,直接使用sql 查询

    * @parem $level 层级,默认1 *
    */ function getSon($id,$array=array(),$level=1) { $f_name=__FUNCTION__; // 定义当前函数名 static $list; //$array=Db::table('table_name')->where('pid',$id)->select(); TP5 foreach ($array as $k => $v) { if($v['pid'] == $id) { $flg = str_repeat('|--',$level); // 更新 名称值 $v['n'] = $flg.$v['n']; // 输出 名称 echo $v['n']."<br/>"; //存放数组中 $list[] = $v;
           // 删除查询过的数组
            unset($array[$k]); $f_name(
    $v['id'],$array,$level+1); } } return $list; }
    // 调用
    $list=$f_name(1,$array);

     调用结果:

    |--邯郸市
    |--|--永年区
    |--|--|--永年区镇
    |--武安市
  • 相关阅读:
    个人亲历运维面试
    《Kubernetes进阶实战》之管理Pod资源对象
    Docker容器必备技能 -- iptables
    vue后台管理权限正确思路
    Axios 各种请求方式传递参数格式
    Cookie的使用(js-cookie插件)
    微信小程序template模板与component组件的区别和使用
    如何机智地回答浏览器兼容性问题
    webpack系列5:源码流程,webpack编译流程
    webpack系列4:文件分析.
  • 原文地址:https://www.cnblogs.com/xuey/p/8629487.html
Copyright © 2011-2022 走看看