Chỉnh sửa:
Trước đây, tôi đã đăng một giải pháp để xây dựng một mảng đa chiều từ đầu ra mà bạn đưa ra cũng như một cách để lấy tất cả các phần tử con của một id
cụ thể ra khỏi mảng cụ thể đó. Bây giờ tôi đã tìm ra cách truy xuất các phần tử con ngay từ đầu ra của bạn (mà không cần phải đi qua buildtree()
trước tiên chức năng:
function fetch_recursive($src_arr, $currentid, $parentfound = false, $cats = array())
{
foreach($src_arr as $row)
{
if((!$parentfound && $row['id'] == $currentid) || $row['parent_id'] == $currentid)
{
$rowdata = array();
foreach($row as $k => $v)
$rowdata[$k] = $v;
$cats[] = $rowdata;
if($row['parent_id'] == $currentid)
$cats = array_merge($cats, fetch_recursive($src_arr, $row['id'], true));
}
}
return $cats;
}
Để sử dụng hàm trên, chỉ cần chuyển vào mảng đầu ra $data
đến đối số đầu tiên và id
bạn muốn truy xuất các phần tử con từ đối số thứ hai:
ví dụ:
$list = fetch_recursive($data, 3);
Điều này sẽ cung cấp cho bạn cấu trúc mảng chính xác cho id
3
(như được thấy trong ví dụ trong hộp mã cuối cùng cho câu trả lời này).
Câu trả lời gốc:
Tôi chưa bao giờ viết một hàm đệ quy để xây dựng các cây lồng nhau từ thiết kế này cho đến bây giờ. Tôi chắc rằng có rất nhiều người khác đã viết các hàm tương tự, nhưng cái này chắc chắn sẽ phù hợp với bạn:
function buildtree($src_arr, $parent_id = 0, $tree = array())
{
foreach($src_arr as $idx => $row)
{
if($row['parent_id'] == $parent_id)
{
foreach($row as $k => $v)
$tree[$row['id']][$k] = $v;
unset($src_arr[$idx]);
$tree[$row['id']]['children'] = buildtree($src_arr, $row['id']);
}
}
ksort($tree);
return $tree;
}
Hàm này sẽ tạo một cách đệ quy một cây từ một danh sách kề và giữ cho id được sắp xếp theo thứ tự tăng dần. Điều này cũng làm cho id
của mỗi cha / con là khóa của mỗi mảng thông tin.
Mã này:
$r = mysql_query("SELECT * FROM test ");
$data = array();
while($row = mysql_fetch_assoc($r)) {
$data[] = $row;
}
echo '<pre>';
print_r(buildtree($data));
echo '</pre>';
'; Sẽ xuất ra một cái gì đó như thế này:
Array
(
[1] => Array
(
[id] => 1
[name] => Electronics
[parent_id] => 0
[children] => Array
(
[2] => Array
(
[id] => 2
[name] => Televisions
[parent_id] => 1
[children] => Array
(
[4] => Array
(
[id] => 4
[name] => Tube
[parent_id] => 2
[children] => Array()
)
[5] => Array
(
[id] => 5
[name] => LCD
[parent_id] => 2
[children] => Array()
)
[6] => Array
(
[id] => 6
[name] => Plasma
[parent_id] => 2
[children] => Array()
)
)
)
[3] => Array
(
[id] => 3
[name] => Portable Electronics
[parent_id] => 1
[children] => Array
(
[7] => Array
(
[id] => 7
[name] => Mp3 Players
[parent_id] => 3
[children] => Array
(
[10] => Array
(
[id] => 10
[name] => Flash
[parent_id] => 7
[children] => Array()
)
)
)
[8] => Array
(
[id] => 8
[name] => CD Players
[parent_id] => 3
[children] => Array()
)
[9] => Array
(
[id] => 9
[name] => 2 Way Radios
[parent_id] => 3
[children] => Array()
)
)
)
)
)
)
Để nhận tất cả các nút con của một id
cụ thể trên mảng một chiều, bạn có thể sử dụng hàm này:
function fetch_recursive($tree, $parent_id, $parentfound = false, $list = array())
{
foreach($tree as $k => $v)
{
if($parentfound || $k == $parent_id)
{
$rowdata = array();
foreach($v as $field => $value)
if($field != 'children')
$rowdata[$field] = $value;
$list[] = $rowdata;
if($v['children'])
$list = array_merge($list, fetch_recursive($v['children'], $parent_id, true));
}
elseif($v['children'])
$list = array_merge($list, fetch_recursive($v['children'], $parent_id));
}
return $list;
}
Dựa trên buildtree()
ở trên, giả sử chúng ta muốn lấy tất cả các nút con của id
3:
echo '<pre>';
print_r(fetch_recursive(buildtree($a), 3));
echo '</pre>';
'; Điều này sẽ xuất ra:
Array
(
[0] => Array
(
[id] => 3
[name] => Portable Electronics
[parent_id] => 1
)
[1] => Array
(
[id] => 7
[name] => Mp3 Players
[parent_id] => 3
)
[2] => Array
(
[id] => 10
[name] => Flash
[parent_id] => 7
)
[3] => Array
(
[id] => 8
[name] => CD Players
[parent_id] => 3
)
[4] => Array
(
[id] => 9
[name] => 2 Way Radios
[parent_id] => 3
)
)