/**
* $sourceArr 原来的数组
* $key 主键
* $parentKey 与主键关联的父主键
* $childrenKey 生成的孩子的键名
*
*/
function arrayToTree($sourceArr, $key, $parentKey, $childrenKey)
{
$tempSrcArr = array();
foreach ($sourceArr as $v)
{
$tempSrcArr[$v[$key]] = $v;
}
$i = 0;
$count = count($sourceArr);
for($i = ($count - 1); $i >=0; $i--)
{
if (isset($tempSrcArr[$sourceArr[$i][$parentKey]]))
{
$tArr = array_pop($tempSrcArr);
$tempSrcArr[$tArr[$parentKey]][$childrenKey] = (isset($tempSrcArr[$tArr[$parentKey]][$childrenKey]) && is_array($tempSrcArr[$tArr[$parentKey]][$childrenKey])) ? $tempSrcArr[$tArr[$parentKey]][$childrenKey] : array();
array_push ($tempSrcArr[$tArr[$parentKey]][$childrenKey], $tArr);
}
}
return $tempSrcArr;
}
/**
* 将数组转换成树
* 例子:将 array(
array('id'=>1,'parentId' => 0,'name'=> 'name1')
,array('id'=>2,'parentId' => 0,'name'=> 'name2')
,array('id'=>4,'parentId' => 1,'name'=> 'name1_4')
,array('id'=>15,'parentId' => 1,'name'=> 'name1_5')
);转换成
* Array(
[1] => Array([id] => 1
[parentId] => 0
[name] => name1
[children] => Array(
[0] => Array([id] => 15,[parentId] => 1,[name] => name1_5)
[1] => Array([id] => 4,[parentId] => 1,[name] => name1_4)
)
)
[2] => Array([id] => 2,[parentId] => 0,[name] => name2)
)
* @param array $sourceArr 要转换的数组
* @param string $key 数组中确认父子的key,例子中为“id”
* @param string $parentKey 数组中父key,例子中为“parentId”
* @param type $childrenKey 要在树节点上索引子节点的key,例子中为“children”
* @return array 返回生成的树
*/
function arrayToTree($sourceArr, $key, $parentKey, $childrenKey)
{
$tempSrcArr = array();
$allRoot = TRUE;
foreach ($sourceArr as $v)
{
$isLeaf = TRUE;
foreach ($sourceArr as $cv )
{
if (($v[$key]) != $cv[$key])
{
if ($v[$key] == $cv[$parentKey])
{
$isLeaf = FALSE;
}
if ($v[$parentKey] == $cv[$key])
{
$allRoot = FALSE;
}
}
}
if ($isLeaf)
{
$leafArr[$v[$key]] = $v;
}
$tempSrcArr[$v[$key]] = $v;
}
if ($allRoot)
{
return $tempSrcArr;
}
else
{
unset($v, $cv, $sourceArr, $isLeaf);
foreach ($leafArr as $v)
{
if (isset($tempSrcArr[$v[$parentKey]]))
{
$tempSrcArr[$v[$parentKey]][$childrenKey] = (isset($tempSrcArr[$v[$parentKey]][$childrenKey]) && is_array($tempSrcArr[$v[$parentKey]][$childrenKey])) ? $tempSrcArr[$v[$parentKey]][$childrenKey] : array();
array_push ($tempSrcArr[$v[$parentKey]][$childrenKey], $v);
unset($tempSrcArr[$v[$key]]);
}
}
unset($v);
return arrayToTree($tempSrcArr, $key, $parentKey, $childrenKey);
}
}
/**递归方法:**/
$rows = array(
0 => array('id' => 1, 'name' => '菜单1', 'parentId' => 0)
, 1 => array('id' => 2, 'name' => '菜单2', 'parentId' => 0)
, 2 => array('id' => 3, 'name' => '菜单3', 'parentId' => 0)
, 3 => array('id' => 4, 'name' => '菜单1_1', 'parentId' => 1)
, 4 => array('id' => 5, 'name' => '菜单1_2', 'parentId' => 1)
, 5 => array('id' => 6, 'name' => '菜单2_1', 'parentId' => 2)
);
print_r(getTree($rows, 0, 'id', 'parentId'));
/**
* 数组根据父id生成树
* @staticvar int $depth 递归深度
* @param array $data 数组数据
* @param integer $pid 父id的值
* @param string $key id在$data数组中的键值
* @param string $chrildKey 要生成的子的键值
* @param string $pKey 父id在$data数组中的键值
* @param int $maxDepth 最大递归深度,防止无限递归
* @return array 重组后的数组
*/
function getTree($data, $pid = 0, $key = 'id', $pKey = 'parentId', $childKey = 'child', $maxDepth = 0){
static $depth = 0;
$depth++;
if (intval($maxDepth) <= 0)
{
$maxDepth = count($data) * count($data);
}
if ($depth > $maxDepth)
{
exit("error recursion:max recursion depth {$maxDepth}");
}
$tree = array();
foreach ($data as $rk => $rv)
{
if ($rv[$pKey] == $pid)
{
$rv[$childKey] = getTree($data, $rv[$key], $key, $pKey, $childKey, $maxDepth);
$tree[] = $rv;
}
}
return $tree;
}
update 2014-04-17
/**
* 生成树列表
*
*/
static function createGroupSelect($haystack, $focusOpt = false){
$result = '<select name="pid">';
$groupTree = getTree($haystack, 0, 'ag_id', 'ag_pid');
echo $result.createOption($groupTree, $focusOpt).'</select>';
}
/**
* 根据树生成option
*
*/
static function createOption($tree, $focusOpt = false, $deepth = 0){
foreach($tree as $gtv){
$nullStr = ($deepth == 0) ? '' : str_repeat(' ', $deepth * 4 - 1);
$preStr = ($deepth == 0) ? '' : (isset($gtv['last']) ? '└' : '├');
if ($focusOpt && ($gtv['ag_id'] == $focusOpt)){
$result .= '<option value="'.$gtv['ag_id'].'" selected >'.$nullStr.$preStr.$gtv['ag_name'].'</option>';
}else{
$result .= '<option value="'.$gtv['ag_id'].'">'.$nullStr.$preStr.$gtv['ag_name'].'</option>';
}
if(!empty($gtv['child'])){
$result .= createOption($gtv['child'], $focusOpt, $deepth+1);
}
}
return $result;
}
/**
* 数组根据父id生成树
* @staticvar int $depth 递归深度
* @param array $data 数组数据
* @param integer $pid 父id的值
* @param string $key id在$data数组中的键值
* @param string $chrildKey 要生成的子的键值
* @param string $pKey 父id在$data数组中的键值
* @param int $maxDepth 最大递归深度,防止无限递归
* @return array 重组后的数组
*/
static function getTree($data, $pid = 0, $key = 'id', $pKey = 'parentId', $childKey = 'child', $maxDepth = 0){
static $depth = 0;
$depth++;
if (intval($maxDepth) <= 0)
{
$maxDepth = count($data) * count($data);
}
if ($depth > $maxDepth)
{
exit("error recursion:max recursion depth {$maxDepth}");
}
$tree = array();
foreach ($data as $rk => $rv)
{
if ($rv[$pKey] == $pid)
{
$rv[$childKey] = getTree($data, $rv[$key], $key, $pKey, $childKey, $maxDepth);
$tree[] = $rv;
}
}
if(!empty($tree)){
$tree[count($tree) - 1]['last'] = 1;
}
return $tree;
}