Berikut adalah versi "ramah pengembang" dari "satu kueri , tidak ada rekursi " solusi untuk masalah ini.
SQL :
SELECT id, parent_id, title, link, position FROM menu_item ORDER BY parent_id, position;
PHP :
$html = '';
$parent = 0;
$parent_stack = array();
// $items contains the results of the SQL query
$children = array();
foreach ( $items as $item )
$children[$item['parent_id']][] = $item;
while ( ( $option = each( $children[$parent] ) ) || ( $parent > 0 ) )
{
if ( !empty( $option ) )
{
// 1) The item contains children:
// store current parent in the stack, and update current parent
if ( !empty( $children[$option['value']['id']] ) )
{
$html .= '<li>' . $option['value']['title'] . '</li>';
$html .= '<ul>';
array_push( $parent_stack, $parent );
$parent = $option['value']['id'];
}
// 2) The item does not contain children
else
$html .= '<li>' . $option['value']['title'] . '</li>';
}
// 3) Current parent has no more children:
// jump back to the previous menu level
else
{
$html .= '</ul>';
$parent = array_pop( $parent_stack );
}
}
// At this point, the HTML is already built
echo $html;
Anda hanya perlu memahami penggunaan variabel $parent_stack.
Ini adalah tumpukan "LIFO" (Masuk Terakhir, Keluar Pertama) - gambar dalam artikel Wikipedia bernilai ribuan kata:http://en.wikipedia.org/wiki/LIFO_%28computing%29
Saat opsi menu memiliki sub-opsi, kami menyimpan ID induknya di tumpukan:
array_push( $parent_stack, $parent );
Dan kemudian, kami segera memperbarui $parent, menjadikannya sebagai ID opsi menu saat ini:
$parent = $option['value']['id'];
Setelah kita mengulang semua sub-opsinya, kita dapat kembali ke level sebelumnya:
$parent = array_pop( $parent_stack );
Inilah sebabnya kami menyimpan ID induk di tumpukan!
Saran saya:renungkan cuplikan kode di atas, dan pahami.
Pertanyaan dipersilakan!
Salah satu keuntungan yang saya lihat dalam pendekatan ini adalah menghilangkan risiko masuk ke infinite loop, yang dapat terjadi saat rekursi digunakan.