Tree.class.php 6.0 KB

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