Hier is een "ontwikkelaarvriendelijke" versie van de "één zoekopdracht , geen recursie " oplossing voor dit probleem.
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;
U hoeft alleen het gebruik van de variabele $parent_stack te begrijpen.
Het is een "LIFO"-stack (Last In, First Out) - de afbeelding in het Wikipedia-artikel zegt meer dan duizend woorden:http://en.wikipedia.org/wiki/LIFO_%28computing%29
Als een menuoptie subopties heeft, slaan we de bovenliggende ID op in de stapel:
array_push( $parent_stack, $parent );
En dan werken we $parent onmiddellijk bij, waardoor het de huidige menu-optie-ID wordt:
$parent = $option['value']['id'];
Nadat we alle subopties hebben doorlopen, kunnen we terugkeren naar het vorige niveau:
$parent = array_pop( $parent_stack );
Daarom hebben we de ouder-ID in de stapel opgeslagen!
Mijn suggestie is:overweeg het bovenstaande codefragment en begrijp het.
Vragen zijn welkom!
Een van de voordelen die ik in deze benadering zie, is dat het het risico elimineert dat je in een oneindige lus terechtkomt, wat kan gebeuren wanneer recursie wordt gebruikt.