Tree.php 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CoreThink [ Simple Efficient Excellent ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2014 http://www.corethink.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Author: <http://www.corethink.cn>
  8. // +----------------------------------------------------------------------
  9. namespace com;
  10. /**
  11. * 列表树生成工具类
  12. * 该类里的方法一部分来自OneThink,一部分来自网络,最后加上作者的修改形成完善的Tree类
  13. * @author
  14. */
  15. class Tree{
  16. /**
  17. * 用于树型数组完成递归格式的全局变量
  18. * @author
  19. */
  20. private $formatTree;
  21. /**
  22. * 将格式数组转换为基于标题的树(实际还是列表,只是通过在相应字段加前缀实现类似树状结构)
  23. * @param array $list
  24. * @param integer $level 进行递归时传递用的参数
  25. */
  26. private function _toFormatTree($list, $level = 0, $title = 'label'){
  27. foreach($list as $key=>$val){
  28. $title_prefix = str_repeat("&nbsp;", $level*4);
  29. $val['level'] = $level;
  30. $val['title_show'] = $level == 0 ? $val[$title] : $title_prefix.$val[$title];
  31. if(!array_key_exists('_child', $val)){
  32. array_push($this->formatTree, $val);
  33. }else{
  34. $child = $val['_child'];
  35. unset($val['_child']);
  36. array_push($this->formatTree, $val);
  37. $this->_toFormatTree($child, $level+1, $title); //进行下一层递归
  38. }
  39. }
  40. return;
  41. }
  42. /**
  43. * 将格式数组转换为树
  44. * @param array $list
  45. * @param integer $level 进行递归时传递用的参数
  46. */
  47. public function toFormatTree($list, $title = 'title', $pk='id', $pid = 'pid', $root = 0, $strict = true){
  48. $list = $this->list_to_tree($list, $pk, $pid, '_child', $root, $strict);
  49. $this->formatTree = array();
  50. $this->_toFormatTree($list, 0, $title);
  51. return $this->formatTree;
  52. }
  53. /**
  54. * 将数据集转换成Tree(真正的Tree结构)
  55. * @param array $list 要转换的数据集
  56. * @param string $pk ID标记字段
  57. * @param string $pid parent标记字段
  58. * @param string $child 子代key名称
  59. * @param string $root 返回的根节点ID
  60. * @param string $strict 默认严格模式
  61. * @param array $filter 要剔除掉的字段
  62. * @return array
  63. */
  64. public function list_to_tree($list, $pk='id', $pid = 'pid', $child = 'child', $root = 0, $strict = true,$filter = array()){
  65. // 创建Tree
  66. $tree = array();
  67. if(is_array($list)){
  68. // 创建基于主键的数组引用
  69. $refer = array();
  70. foreach($list as $key => $data){
  71. $refer[$data[$pk]] =& $list[$key];
  72. }
  73. foreach($list as $key => $data){
  74. // 判断是否存在parent
  75. $parent_id = $data[$pid];
  76. if($parent_id === null || (int)$root === (int)$parent_id){
  77. $tree[] =& $list[$key];
  78. }else{
  79. if(isset($refer[$parent_id])){
  80. $parent =& $refer[$parent_id];
  81. $parent['children'][] =& $list[$key];
  82. }else{
  83. if($strict === false){
  84. $tree[] =& $list[$key];
  85. }
  86. }
  87. }
  88. }
  89. //剔除数据
  90. if(count($filter) > 0){
  91. foreach($refer as $key => $data){
  92. foreach ($data as $k => $v) {
  93. if(in_array($k, $filter)) unset($refer[$key][$k]);
  94. }
  95. }
  96. }
  97. }
  98. return $tree;
  99. }
  100. /**
  101. * 将list_to_tree的树还原成列表
  102. * @param array $tree 原来的树
  103. * @param string $child 孩子节点的键
  104. * @param string $order 排序显示的键,一般是主键 升序排列
  105. * @param array $list 过渡用的中间数组,
  106. * @return array 返回排过序的列表数组
  107. */
  108. public function tree_to_list($tree, $child = '_child', $order='id', &$list = array()){
  109. if(is_array($tree)){
  110. foreach ($tree as $key => $value){
  111. $reffer = $value;
  112. if(isset($reffer[$child])){
  113. unset($reffer[$child]);
  114. tree_to_list($value[$child], $child, $order, $list);
  115. }
  116. $list[] = $reffer;
  117. }
  118. $list = $this->list_sort_by($list, $order, $sortby='asc');
  119. }
  120. return $list;
  121. }
  122. /**
  123. * 对查询结果集进行排序
  124. * @access public
  125. * @param array $list 查询结果
  126. * @param string $field 排序的字段名
  127. * @param array $sortby 排序类型 asc正向排序 desc逆向排序 nat自然排序
  128. * @return array
  129. */
  130. public function list_sort_by($list,$field, $sortby='asc'){
  131. if(is_array($list)){
  132. $refer = $resultSet = array();
  133. foreach($list as $i => $data)
  134. $refer[$i] = &$data[$field];
  135. switch($sortby){
  136. case 'asc': // 正向排序
  137. asort($refer);
  138. break;
  139. case 'desc':// 逆向排序
  140. arsort($refer);
  141. break;
  142. case 'nat': // 自然排序
  143. natcasesort($refer);
  144. break;
  145. }
  146. foreach ($refer as $key=> $val)
  147. $resultSet[] = &$list[$key];
  148. return $resultSet;
  149. }
  150. return false;
  151. }
  152. /**
  153. * 在数据列表中搜索
  154. * @access public
  155. * @param array $list 数据列表
  156. * @param mixed $condition 查询条件
  157. * 支持 array('name'=>$value) 或者 name=$value
  158. * @return array
  159. */
  160. function list_search($list,$condition){
  161. if(is_string($condition))
  162. parse_str($condition, $condition);
  163. //返回的结果集合
  164. $resultSet = array();
  165. foreach ($list as $key => $data){
  166. $find = false;
  167. foreach ($condition as $field=>$value){
  168. if(isset($data[$field])){
  169. if(0 === strpos($value,'/')){
  170. $find = preg_match($value,$data[$field]);
  171. }elseif($data[$field]==$value){
  172. $find = true;
  173. }
  174. }
  175. }
  176. if($find){
  177. $resultSet[] = &$list[$key];
  178. }
  179. }
  180. return $resultSet;
  181. }
  182. }