php数组转换成树的几个例子

下面我整理了一些常用的数组转换成树的实例与大家一起学习,我想大家都会很喜欢这篇文章的.Php代码如下:

  1. * $sourceArr 原来的数组
  2. * $key 主键
  3. * $parentKey 与主键关联的父主键
  4. * $childrenKey 生成的孩子的键名
  5. *
  6. */
  7. function arrayToTree($sourceArr, $key, $parentKey, $childrenKey)
  8. {
  9. $tempSrcArr = array();
  10. foreach ($sourceArr as $v)
  11. {
  12. $tempSrcArr[$v[$key]] = $v;
  13. }
  14. $i = 0;
  15. $count = count($sourceArr);
  16. for($i = ($count - 1); $i >=0; $i--)
  17. {
  18. if (isset($tempSrcArr[$sourceArr[$i][$parentKey]]))
  19. {
  20. $tArr = array_pop($tempSrcArr);
  21. $tempSrcArr[$tArr[$parentKey]][$childrenKey] = (isset($tempSrcArr[$tArr[$parentKey]][$childrenKey]) && is_array($tempSrcArr[$tArr[$parentKey]][$childrenKey])) ? $tempSrcArr[$tArr[$parentKey]][$childrenKey] : array();
  22. array_push ($tempSrcArr[$tArr[$parentKey]][$childrenKey], $tArr);
  23. }
  24. }
  25. return $tempSrcArr;
  26. }

PHP代码如下:

  1. * 将数组转换成树
  2. * 例子:将 array(
  3. array('id'=>1,'parentId' => 0,'name'=> 'name1')
  4. ,array('id'=>2,'parentId' => 0,'name'=> 'name2')
  5. ,array('id'=>4,'parentId' => 1,'name'=> 'name1_4')
  6. ,array('id'=>15,'parentId' => 1,'name'=> 'name1_5')
  7. );
  8. /*转换成
  9. * Array(
  10. [1] => Array([id] => 1
  11. [parentId] => 0
  12. [name] => name1
  13. [children] => Array(
  14. [0] => Array([id] => 15,[parentId] => 1,[name] => name1_5)
  15. [1] => Array([id] => 4,[parentId] => 1,[name] => name1_4)
  16. )
  17. )
  18. [2] => Array([id] => 2,[parentId] => 0,[name] => name2)
  19. )
  20. */

* @param array $sourceArr 要转换的数组

* @param string $key 数组中确认父子的key,例子中为“id”

* @param string $parentKey 数组中父key,例子中为“parentId”

* @param type $childrenKey 要在树节点上索引子节点的key,例子中为“children”

* @return array 返回生成的树

PHP代码如下:

  1. function arrayToTree($sourceArr, $key, $parentKey, $childrenKey)
  2. {
  3. $tempSrcArr = array();
  4. $allRoot = TRUE;
  5. foreach ($sourceArr as $v)
  6. {
  7. $isLeaf = TRUE;
  8. foreach ($sourceArr as $cv )
  9. {
  10. if (($v[$key]) != $cv[$key])
  11. {
  12. if ($v[$key] == $cv[$parentKey])
  13. {
  14. $isLeaf = FALSE;
  15. }
  16. if ($v[$parentKey] == $cv[$key])
  17. {
  18. $allRoot = FALSE;
  19. }
  20. }
  21. }
  22. if ($isLeaf)
  23. {
  24. $leafArr[$v[$key]] = $v;
  25. }
  26. $tempSrcArr[$v[$key]] = $v;
  27. }
  28. if ($allRoot)
  29. {
  30. return $tempSrcArr;
  31. }
  32. else
  33. {
  34. unset($v, $cv, $sourceArr, $isLeaf);
  35. foreach ($leafArr as $v)
  36. {
  37. if (isset($tempSrcArr[$v[$parentKey]]))
  38. {
  39. $tempSrcArr[$v[$parentKey]][$childrenKey] = (isset($tempSrcArr[$v[$parentKey]][$childrenKey]) && is_array($tempSrcArr[$v[$parentKey]][$childrenKey])) ? $tempSrcArr[$v[$parentKey]][$childrenKey] : array();
  40. array_push ($tempSrcArr[$v[$parentKey]][$childrenKey], $v);
  41. unset($tempSrcArr[$v[$key]]);
  42. }
  43. }
  44. unset($v);
  45. return arrayToTree($tempSrcArr, $key, $parentKey, $childrenKey);
  46. }
  47. }

PHP代码,递归方法:

  1. $rows = array(
  2. 0 => array('id' => 1, 'name' => '菜单1', 'parentId' => 0)
  3. , 1 => array('id' => 2, 'name' => '菜单2', 'parentId' => 0)
  4. , 2 => array('id' => 3, 'name' => '菜单3', 'parentId' => 0)
  5. , 3 => array('id' => 4, 'name' => '菜单1_1', 'parentId' => 1)
  6. , 4 => array('id' => 5, 'name' => '菜单1_2', 'parentId' => 1)
  7. , 5 => array('id' => 6, 'name' => '菜单2_1', 'parentId' => 2)
  8. );
  9. print_r(getTree($rows, 0, 'id', 'parentId'));

代码如下:

  1. /**
  2. * 数组根据父id生成树
  3. * @staticvar int $depth 递归深度
  4. * @param array $data 数组数据
  5. * @param integer $pid 父id的值
  6. * @param string $key id在$data数组中的键值
  7. * @param string $chrildKey 要生成的子的键值
  8. * @param string $pKey 父id在$data数组中的键值
  9. * @param int $maxDepth 最大递归深度,防止无限递归
  10. * @return array 重组后的数组
  11. */
  12. function getTree($data, $pid = 0, $key = 'id', $pKey = 'parentId', $childKey = 'child', $maxDepth = 0){
  13. static $depth = 0;
  14. $depth++;
  15. if (intval($maxDepth) <= 0)
  16. {
  17. $maxDepth = count($data) * count($data);
  18. }
  19. if ($depth > $maxDepth)
  20. {
  21. exit("error recursion:max recursion depth {$maxDepth}");
  22. }
  23. $tree = array();
  24. foreach ($data as $rk => $rv)
  25. {
  26. if ($rv[$pKey] == $pid)
  27. {
  28. $rv[$childKey] = getTree($data, $rv[$key], $key, $pKey, $childKey, $maxDepth);
  29. $tree[] = $rv;
  30. }
  31. }
  32. return $tree;
  33. }

一个实例,代码如下:

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
  6. <title>TREE</title>
  7. <style type="text/css">
  8. /*树的全局CSS*/
  9. .kyp_tree{
  10. font: 12px/2.5 verdana;
  11. float:left;display:inline;
  12. }
  13. .kyp_tree dd{
  14. margin:0;padding:0;
  15. margin-left:20px;
  16. }
  17. /*链接*/
  18. .kyp_tree dl a{
  19. font-size:12px;
  20. color:#333;
  21. text-decoration:none;
  22. }
  23. .kyp_tree dl a:hover, .kyp_tree dd dt.red_sub a{
  24. font-size:12px;
  25. color:#AE0002;
  26. }
  27. /*一级dl*/
  28. .kyp_tree dl{
  29. border-bottom:1px dashed #ccc;
  30. margin:0;padding:0;
  31. }
  32. /*次级dl*/
  33. .kyp_tree dl dl, .kyp_tree dl.last{
  34. border:none;
  35. }
  36. .kyp_tree dd dt.currentClass{
  37. background:url(tree_top.gif) no-repeat 0 -24px;
  38. }
  39. /*一级标题*/
  40. .kyp_tree dt{
  41. background:url(tree_top.gif) no-repeat 2px -57px;
  42. padding-left:15px;
  43. cursor:pointer;
  44. font-size:13px;
  45. height:30px;
  46. line-height :27px;
  47. line-height :32px9;
  48. }
  49. /*子标题*/
  50. .kyp_tree dd dt{
  51. background:url(tree_arrow.gif) no-repeat 2px 10px;
  52. font-size:12px;
  53. }
  54. /*一级张开样式*/
  55. .kyp_tree dt.open{
  56. background:url(tree_top.gif) no-repeat 2px 12px;
  57. }
  58. /*张开样式*/
  59. .kyp_tree dd dt.open{
  60. background:url(tree_arrow.gif) no-repeat 0 -25px;
  61. }
  62. /*没有子节点的样式*/
  63. .kyp_tree dt.nosub{
  64. background:none;
  65. }
  66. </style>
  67. <script type="text/javascript">
  68. //<![CDATA[
  69. jQuery.fn.createTree = function (fn, ini){
  70. var $ = jQuery, ini = Object(ini);
  71. this.find('dd').hide();
  72. this.children('dl:last').addClass('last');
  73. this.find('dt', this).each(function (){
  74. var nosub = $(this).next('dd').size() == 0;
  75. if (nosub) {
  76. $(this).addClass('nosub');
  77. }
  78. if (ini.id && ini.id == $(this).attr('classify')) {
  79. $(this).parents('dd').show().prev('dt').addClass('open');
  80. $(this).addClass('red_sub');
  81. if (nosub) {
  82. $(this).addClass('currentClass')
  83. }else{
  84. $(this).next('dd').show();
  85. $(this).addClass('open')
  86. }
  87. }
  88. }).click(function (e){
  89. var dd = $(this).next('dd'),
  90. isClose = dd.css('display') == 'none';
  91. if (dd.size()) {
  92. if (isClose) {
  93. dd.show();
  94. $(this).addClass('open')
  95. }else{
  96. dd.hide();
  97. $(this).removeClass('open')
  98. }
  99. }
  100. return fn && fn.call(this, e, dd)
  101. });
  102. if (ini.mx) {
  103. this.find('dt').click(function (e){
  104. var J = $(this);
  105. if (J.next('dd').size()) {
  106. if (J.hasClass('open')) {
  107. J.parent().siblings('dl').children('dd').hide();
  108. J.parent().siblings('dl').children('dt').removeClass('open');
  109. J.next('dd').show();
  110. J.addClass('open')
  111. }
  112. }
  113. })
  114. }
  115. };
  116. (function ($){
  117. $(function (){
  118. $('#tree_wrap').createTree(function (e, dd){//回调(事件, 下一个dd)
  119. $('#show').html(this.innerHTML+dd.size())
  120. }, {mx: 1, id: 200})// mx是否互斥, id 当前类别
  121. });
  122. })(jQuery)
  123. //]]>
  124. </script>
  125. </head>
  126. <body>
  127. <?php
  128. // 树组的顺序即是分类的顺序,因此前当分类的下级子类一定要紧随其后
  129. $tree= array(
  130. 1 => array('id'=>1, 'cname'=>'一级分类', 'pid'=>0),
  131. 100 => array('id'=>100, 'cname'=>'特意加进去的二级分类', 'pid'=>1),
  132. 101 => array('id'=>101, 'cname'=>'特意加进去的二级分类2222222222', 'pid'=>1),
  133. 2 => array('id'=>2, 'cname'=>'二级分类', 'pid'=>1),
  134. 3 => array('id'=>3, 'cname'=>'三级分类', 'pid'=>2),
  135. 4 => array('id'=>4, 'cname'=>'四级分类', 'pid'=>3),
  136. 5 => array('id'=>5, 'cname'=>'四级分类2', 'pid'=>3),
  137. 200 => array('id'=>200, 'cname'=>'55555', 'pid'=>5),
  138. 6 => array('id'=>6, 'cname'=>'另一级分类', 'pid'=>0),
  139. 7 => array('id'=>7, 'cname'=>'First First First', 'pid'=>0),
  140. 8 => array('id'=>8, 'cname'=>'First First First', 'pid'=>7),
  141. );
  142. // 指定分类ID,返回子类量(不进行深度递归)
  143. function getChildTotal($id)
  144. {
  145. global $tree;
  146. $total = 0;
  147. foreach($tree as $value)
  148. {
  149. if ($id == $value['pid'])
  150. {
  151. $total++;
  152. }
  153. }
  154. return $total;
  155. }
  156. // 指定分类ID,并返回数组(不进行深度递归)
  157. function getChildArray($id)
  158. {
  159. global $tree;
  160. $array = array();
  161. foreach($tree as $key=>$value)
  162. {
  163. if ($id == $value['pid'])
  164. {
  165. $array[$key] = $value;
  166. }
  167. }
  168. return $array;
  169. }
  170. // 递归查询方式将树数组转换成HTML嵌套树
  171. function getTreeHTML($tree,$level = 0)
  172. {
  173. if ($tree)
  174. {
  175. $level += 1;
  176. foreach($tree as $id => $node)
  177. {
  178. $html .= "<dl>";
  179. $html .= '<dt classify="'.$node['id'].'"><a href="http://www.baidu.com/">'.$node['cname']."</a></dt>";
  180. if (getChildTotal($node['id']))
  181. {
  182. $tree_last = getChildArray($node['id']);
  183. $html .= '<dd>';
  184. $html .= getTreeHTML($tree_last,$level);
  185. $html .= '</dd>';
  186. }
  187. $html .= '</dl>';
  188. }
  189. }
  190. return $html;
  191. }
  192. $html = getTreeHTML( getChildArray(0) );
  193. echo '<div class="kyp_tree">';
  194. echo $html;
  195. echo '</div><div ></div>';
  196. ?>
  197. </body>
  198. </html>