/** * File name: TreeTable.class.php * Author: run.gao 312854458@qq.com Date: 2012-07-24 23:22 GMT+8 * Description: Universal table with unlimited levels Category **/ /** * Table display of unlimited categories is to display wireless categories in the form of a table, which can better reflect the affiliation of the categories * Usage method: * 1. Instantiate the category * $ treeTable = new TreeTable(); * 2. Initialize classification, $treearr must be a multi-dimensional array and contain id, parentid, name fields * $treeTable->init($treearr); * 3. Get unlimited classification HTML code * echo $treeTable->get_treetable(); **/ class TreeTable { /** * 2-dimensional array required to generate tree structure * @var array */ public $arr = array(); /** * Number of table columns * @var int */ public $columns = 0; /** * Number of table rows * @var int */ public $rows = 0; /** * Initialize TreeTable data * @param array 2-dimensional array * array( * 1 => array('id'=>'1','parentid'=>0 ,'name'=>'First-level column one'), * 2 => array('id'=>'2','parentid'=>0,'name'=>' First-level column two'), * 3 => array('id'=>'3','parentid'=>1,'name'=>'Second-level column one'), * 4 => array('id'=>'4','parentid'=>1,'name'=>'Second-level column two'), * 5 => array ('id'=>'5','parentid'=>2,'name'=>'Second-level column three'), * 6 => array('id'=>' 6','parentid'=>3,'name'=>'Third-level column one'), * 7 => array('id'=>'7','parentid'=> ;3,'name'=>'Third-level column two') * ) */ public function init($arr=array()){ if(!is_array($arr)) return false; foreach ($arr as $k=> ;$v) { $this->arr[$v['id']] = $v; } foreach ($this->arr as $k => $v ){ $this->arr[$k]['column'] = $this->get_level($v['id']); // Y-axis position $this-> arr[$k]['arrchildid'] = $this->get_arrchildid($v['id']); // All child nodes $this->arr[$k]['arrparentid'] = $this->get_arrparentid($v['id']); // All parent nodes $this->arr[$k]['child_bottom_num'] = $this->get_child_count($v ['id']); // All underlying element nodes } $this->columns = $this->get_columns(); // Total number of rows $this->rows = $this->get_rows(); //Total number of columns // Sort by arrparentid and id number $this->sort_arr(); foreach ($this->arr as $k => $v){ $this->arr[$k]['row'] = $this->get_row_location($v['id']); // X-axis position $this->arr[$k]['rowspan'] = $v['child_bottom_num']; // Number of rows merged $this->arr[$k]['colspan'] = $v['child_bottom_num'] == 0 ? $this->columns - $v['column'] + 1 : 0; //Number of column merges } return $this->get_tree_arr( ); } /** * Get array **/ public function get_tree_arr(){ return is_array($this->arr) ? $this->arr : false; } /** * Reorder the array by arrparentid/id number **/ public function sort_arr(){ // Field to be sorted foreach ($this->arr as $k => $v){ $order_pid_arr[$k] = $v['arrparentid']; $order_iscost[] = $v['sort']; $order_id_arr[$k] = $v ['id']; } // Sort by arrparentid first, then sort by id number array_multisort( $order_pid_arr, SORT_ASC, SORT_STRING, $order_iscost, SORT_DESC, SORT_NUMERIC, $order_id_arr, SORT_ASC, SORT_NUMERIC, $this->arr); // Get each node level for ($column = 1; $column <= $this ->columns; $column++) { $row_level = 0; foreach ($this->arr as $key => $node){ if ($node['column'] == $column){ $row_level++; $this->arr[$key]['column_level'] = $row_level; } } } / / Recalculate using ID as key name foreach ($this->arr as $k=>$v) { $arr[$v['id']] = $v; } $this->arr = $arr; } /** * get parent array * @param int * @return array */ public function get_parent($myid){ $newarr = array(); if(!isset($this->arr[$myid])) return false; $pid = $this->arr[$myid]['parentid']; $pid = $this->arr[$pid]['parentid']; if(is_array($this->arr)){ foreach($this->arr as $id => $a){ if($a['parentid'] == $pid) $newarr[$id] = $a; } } return $newarr; } /** * Get the child array * @param int * @return array */ public function get_child($myid){ $a = $newarr = array(); if(is_array($this->arr)) { foreach($this->arr as $id => $a){ if($a['parentid'] == $myid) $newarr[$id] = $a; } } return $newarr ? $newarr : false; } /** * Get the level of the current node * @param $myid Current node ID number **/ public function get_level($myid, $init = true){ static $level = 1; if($init) $level = 1; if ($this->arr[$myid]['parentid']) { $level++; $this->get_level($this->arr[$myid]['parentid'], false); } return $level; } /** * Get the number of all underlying nodes (nodes without child nodes) of the current node * @param $myid Node ID number * @param $init Static variable will be loaded for the first time **/ public function get_child_count($myid, $init = true){ static $count = 0; if($init) $count = 0; if(!$this->get_child($myid) && $init) return 0; if($childarr = $this->get_child($myid)){ foreach ($childarr as $v){ $this->get_child_count($v['id'], false); } }else{ $count++; } return $count; } /** * Get the ID numbers of all child nodes of the node * @param $catid Node ID number * @param $init The first load will statically initialize the situation **/ public function get_arrchildid($myid, $init = true) { static $childid; if($init) $childid = ''; if(!is_array($this->arr)) return false; foreach($this->arr as $id => $a){ if($a['parentid'] == $myid) { $childid = $childid ? $childid.','.$a['id'] : $a['id']; $this->get_arrchildid($a['id'], false); } } return $childid ; } /** * Get the ID numbers of all parent nodes of this node * @param $id node ID number **/ public function get_arrparentid($id, $arrparentid = '') { if(!is_array($this->arr)) return false; $parentid = $this->arr[$id]['parentid']; if($parentid > 0) $arrparentid = $arrparentid ? $parentid.','.$arrparentid : $parentid; if($parentid) $arrparentid = $this->get_arrparentid($parentid, $arrparentid); return $arrparentid; } /** * Get the row location of the node * @param $myid node ID number */ public function get_row_location($myid){ $nodearr = $this->arr; // 获取每一个节点所在行的位置 foreach ($nodearr as $key => $node){ if($myid == $node['id']) { $node_row_count = 0; $arrparentid = explode(',', $node['arrparentid']); // 所有父节点小于当前节点层次的底层节点等于0的元素 foreach ($arrparentid as $pid){ foreach ($nodearr as $node_row){ if($node_row['column'] == $nodearr[$pid]['column'] && $nodearr[$pid]['column_level'] > $node_row['column_level'] && $node_row['child_bottom_num'] == 0){ $node_row_count ++; } } } // 所有当前节点并且节点层次(rowid_level)小于当前节点层次的个数 foreach ($nodearr as $node_row){ if($node['column'] == $node_row['column'] && $node_row['column_level'] < $node['column_level']){ $node_row_count += $node_row['child_bottom_num'] ? $node_row['child_bottom_num'] : 1; } } $node_row_count++; break; } } return $node_row_count; } /** * Get the number of rows in the table **/ public function get_rows(){ $row = 0; foreach ($this->arr as $key => $node){ if($node['child_bottom_num'] == 0){ $rows++; // 总行数 } } return $rows; } /** * Get the number of columns in the table **/ public function get_columns(){ $columns = 0 ; foreach ($this->arr as $key => $node){ if($node['column'] > $columns){ $columns = $node['column']; // 总列数 } } return $columns; } /** * Get the table display format of the category (excluding headers) **/ public function get_treetable(){ $table_string = ''; for($row = 1; $row <= $this->rows; $row++){ $table_string .= "rt |