php 树形列表

TreeView.php

<?php
class TreeView {
    public $childName = "child";
    public $parentid;
    public $id;
    public $nameColumn;
    function __construct($parentid, $id,$nameColumn) {
        $this->parentid = $parentid;
        $this->id = $id;
        $this->nameColumn=$nameColumn;
    }
    
    public function display($Nodes) {
        echo '<div class="TreeView"><ul>';
        $GroupNodes = $this->buildTree($Nodes->list, $this->parentid, $this->id);
        $this->showTree($GroupNodes);
        echo '</ul>';
    }

    function buildTree($temp, $parentid, $idKey) {
        $grouped = $this->reGroup($temp, $parentid, $idKey);
        $fnBuilder = function ($siblings) use(&$fnBuilder, $grouped, $idKey) {
            foreach ($siblings as $k => $sibling) {
                $id = $sibling[$idKey];
                if (isset($grouped[$id])) {
                    $sibling[$this->childName] = $fnBuilder($grouped[$id]);
                }
                $siblings[$k] = $sibling;
            }
            return $siblings;
        };
        $tree = $fnBuilder($grouped[0]);
        return $tree;
    }


    function showTree($grouped) {
       foreach($grouped as $subGroupKey=>$subGroup){
           if(is_array($subGroup)){              
               if($subGroupKey===$this->childName){
                   //当前有子集
                   echo '<ul>';
                   $this->showTree($subGroup);
                   echo '</ul></li>';
               }else{
                   echo '</li>';
                   $this->showTree($subGroup);
               }
           }else{
               if($subGroupKey===$this->nameColumn){
                   echo '<li><div class="clickOnCollpose"><div class="title"><a>'.$subGroup.'</a></div></div>';
               }
           }
       }
    }
   
    function reGroup($temp, $parentid, $id) {
        $group = array();
        foreach ($temp as $item) {
            $key = $item[$parentid];
            $group[$key][] = $item;
        }
        return $group;
    }
    
}
class Nodes{
    public $list;

    function __construct(){
        $this->list=array();
    }

    public function add($Node) {
        array_push($this->list, $Node);
    }
    public function removeByNode($Node) {
        for ($i = 0;$i < count($this->list);$i++) {
            if ($this->list[$i] === $Node) {
                $this->remove($i);
            }
        }
    }
    public function removeByIndex($startIndex, $length = 0) {
        array_splice($this->list, $startIndex, $lenght);
    }
    public function clear() {
        unset($this->list);        
    }    
}

?>

TreeView.css

ul{
    list-style:none;
    padding-left: 1em;
}
.clickOnCollpose{
    display: inline-block;
    background-color: #eee;
    width:100%;
    margin:4px 0px 4px 0px;
    border-radius: 6px;
    border-width: 1px;
    border-color: #aaa;
    border-style: solid;
    padding:4px;
}

.clickOnCollpose:hover{
    background-color: #337ABC;
    color:#FFFFFF;
    padding:4px;
    border-color:#FFF;
}

.title{
    float:left;
    text-indent: 10px;
}
.count-near{
    background-color:#FF0000;
    border-radius:20px;
    color:#FFF;
    font-weight:bold;
    width:20px;
    height:20px;
    text-align:center;
    float:left;
    margin-left:20px;
}
.count-far{
    background-color:#FF0000;
    border-radius:20px;
    color:#FFF;
    font-weight:bold;
    width:20px;
    height:20px;
    text-align:center;
    float:right;
}


li{
    cursor:hand;
}
.treeview{
   width:100%;
}

TreeView.js

$(document).ready(function(){
    //默认从第2级隐藏
    $(".treeView ul li").find("ul").toggle();
 
    $(".clickOnCollpose").on('click',function(){    
        //展开/收缩下级
        $(this).parent().find("ul").toggle();  
 
        //展开/收缩下下级
        $(this).parent().find("ul li ul").toggle();        
    })
 
    $(".clickOnCollpose").mouseenter(function(){
        var count=$(this).next().children().length;
        //if(count>0){
            //class修改成 count-near 更改样式
            $(this).append("<div class='count-far'> "+count+" </div>");       
        //}
    })
 
    $(".clickOnCollpose").mouseleave(function(){     
        //class修改成 count-near 更改样式
         $(this).find(".count-far").remove();
    })
 
})

==============================================================

Demo.php

<?php
require_once("TreeView.php");
?>

<html>
<head>
<title>测试</title>
<link rel="stylesheet" href="./TreeView.css" type="text/css"/>
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<script src="./TreeView.js"></script>
</head>
<body>

<?php

$n=new Nodes();
$n->add( ["id" => 1, "name" => "name0-1", "parentid" => 0]);
$n->add( ["id" => 2, "name" => "name1-2", "parentid" => 1]);
$n->add( ["id" => 3, "name" => "name1-3", "parentid" => 1]);
$n->add( ["id" => 4, "name" => "name2-4", "parentid" => 2]);
$n->add( ["id" => 5, "name" => "name2-5", "parentid" => 2]);
$n->add( ["id" => 6, "name" => "name4-6", "parentid" => 4]);
$n->add( ["id" => 7, "name" => "name1-7", "parentid" => 1]);
$n->add( ["id" => 8, "name" => "name2-8", "parentid" => 2]);
$n->add( ["id" => 9, "name" => "name2-9", "parentid" => 2]);
$n->add( ["id" => 10, "name" => "name2-10", "parentid" => 2]);
$n->add( ["id" => 11, "name" => "name8-11", "parentid" => 8]);
$n->add( ["id" => 12, "name" => "name8-12", "parentid" => 8]);
$n->add( ["id" => 13, "name" => "name11-13", "parentid" => 11]);
$n->add( ["id" => 14, "name" => "name0-14", "parentid" => 0]);
$n->add( ["id" => 15, "name" => "name0-15", "parentid" => 0]);


$treeview=new TreeView("parentid","id","name");
//可写作$treeview=new TreeView(2,0,1);
$treeview->display($n);
?>
</body>
</html>