Tree.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <?php
  2. /**
  3. *------------------------------------------------------
  4. * Tree.php
  5. *------------------------------------------------------
  6. *
  7. * @author qqiu@qq.com
  8. * @date 2016/5/26 11:17
  9. * @version V1.0
  10. *
  11. */
  12. namespace App\Services\Base;
  13. class Tree {
  14. /**
  15. * 生成树型结构所需要的2维数组
  16. */
  17. public $arr = array();
  18. /**
  19. * 生成树型结构所需修饰符号
  20. */
  21. public $icon = array('│','├','└');
  22. public $nbsp = "&nbsp;";
  23. public $treeArr = array();
  24. /**
  25. * 构造函数,初始化类
  26. * @param array 2维数组,例如:
  27. * array(
  28. * 1 => array('id'=>'1','pid'=>0,'name'=>'一级栏目一'),
  29. * 2 => array('id'=>'2','pid'=>0,'name'=>'一级栏目二'),
  30. * 3 => array('id'=>'3','pid'=>1,'name'=>'二级栏目一'),
  31. * 4 => array('id'=>'4','pid'=>1,'name'=>'二级栏目二'),
  32. * 5 => array('id'=>'5','pid'=>2,'name'=>'二级栏目三'),
  33. * 6 => array('id'=>'6','pid'=>3,'name'=>'三级栏目一'),
  34. * 7 => array('id'=>'7','pid'=>3,'name'=>'三级栏目二'),
  35. * )
  36. */
  37. public function init($arr = [])
  38. {
  39. $data = array();
  40. foreach ($arr AS $val){
  41. $data[$val['id']] = $val;
  42. }
  43. $this->arr = $data;
  44. $this->treeArr = array();
  45. return is_array($data);
  46. }
  47. /**
  48. * 得到父级数组
  49. * @param int
  50. * @return array
  51. */
  52. public function getParent($myid)
  53. {
  54. $newarr = array();
  55. if(!isset($this->arr[$myid])) return false;
  56. $pid = $this->arr[$myid]['pid'];
  57. if(isset($this->arr[$pid]['pid'])){
  58. $pid = $this->arr[$pid]['pid'];
  59. }
  60. if(is_array($this->arr)){
  61. foreach($this->arr as $id => $val){
  62. if($val['pid'] == $pid) $newarr[$id] = $val;
  63. }
  64. }
  65. return $newarr;
  66. }
  67. /**
  68. * 得到所有父级数组
  69. * @param int
  70. * @return array
  71. */
  72. public function getAllParents($myid, &$newarr = [])
  73. {
  74. if(!isset($this->arr[$myid])) return false;
  75. $pid = $this->arr[$myid]['pid'];
  76. if(isset($this->arr[$pid])){
  77. $newarr[$pid] = $this->arr[$pid];
  78. $this->getAllParents($pid, $newarr);
  79. }
  80. return array_reverse($newarr, true);
  81. }
  82. /**
  83. * 得到子级数组
  84. * @param int
  85. * @return array
  86. */
  87. public function getChild($myid)
  88. {
  89. $newarr = array();
  90. if(is_array($this->arr)){
  91. foreach($this->arr as $id => $val){
  92. if($val['pid'] == $myid) $newarr[$id] = $val;
  93. }
  94. }
  95. return $newarr ? $newarr : false;
  96. }
  97. /**
  98. * 得到当前位置数组
  99. * @param int
  100. * @return array
  101. */
  102. public function getPos($myid, &$newarr = [])
  103. {
  104. $a = array();
  105. if(!isset($this->arr[$myid])) return false;
  106. $newarr[] = $this->arr[$myid];
  107. $pid = $this->arr[$myid]['pid'];
  108. if(isset($this->arr[$pid])){
  109. $this->getPos($pid, $newarr);
  110. }
  111. if(is_array($newarr)){
  112. krsort($newarr);
  113. foreach($newarr as $v){
  114. $a[$v['id']] = $v;
  115. }
  116. }
  117. return $a;
  118. }
  119. /**
  120. * 得到树型结构
  121. * @param $myid 表示获得这个ID下的所有子级, 默认不包括自身
  122. * @param $spacer 间隔缩进
  123. * @param $self 是否包含自身
  124. */
  125. public function getTree($myid = 0, $spacer = '', $self = false)
  126. {
  127. if($self){
  128. $spacer = $spacer ? $spacer : $this->nbsp;
  129. $selfArr = $this->arr[$myid];
  130. $selfArr['spacer'] = '';
  131. $this->treeArr[] = $selfArr;
  132. }
  133. $number = 1;
  134. $child = $this->getChild($myid);
  135. if(is_array($child)){
  136. $total = count($child);
  137. foreach($child as $value){
  138. $j = $k = '';
  139. if($number == $total){
  140. $j .= $this->icon[2];
  141. }else{
  142. $j .= $this->icon[1];
  143. $k = $spacer ? $this->icon[0] : '';
  144. }
  145. $nbsp = $this->nbsp;
  146. //间隔缩进
  147. $value['spacer'] = $spacer ? $spacer.$j : '';
  148. //层级关系
  149. $value['level'] = count(explode($nbsp, $value['spacer']));
  150. //生成带树状结构的新数组
  151. $this->treeArr[] = $value;
  152. $this->getTree($value['id'], $spacer.$k.$nbsp);
  153. $number++;
  154. }
  155. }
  156. return $this->_cateAppendChild($this->treeArr);
  157. }
  158. /**
  159. * 栏目是否含有子栏目
  160. * @param $cateArr
  161. * @return mixed
  162. */
  163. private function _cateAppendChild($cateArr)
  164. {
  165. //PID集合
  166. $pidArr = [];
  167. foreach($cateArr AS $val){
  168. $pidArr[$val['pid']] = $val['pid'];
  169. }
  170. //栏目ID在PID集合内,则含有子栏目
  171. foreach($cateArr AS $key => $val){
  172. if(in_array($val['id'], $pidArr)){
  173. $cateArr[$key]['child'] = 1;
  174. }else{
  175. $cateArr[$key]['child'] = 0;
  176. }
  177. }
  178. return $cateArr;
  179. }
  180. }