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>\r\n";

        }
    }
    $html.="</ul>\r\n";

    // 删除多余的 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);

 调用结果:

|--邯郸市
|--|--永年区
|--|--|--永年区镇
|--武安市
posted @ 2018-03-23 11:51  柔和的天空  阅读(6087)  评论(0编辑  收藏  举报