Vanilla 1.1.5a is a product of Lussumo. More Information: Documentation, Community Support.
1 to 22 of 22
function _build_menu_tree($list)
{
// If an array wasn't submitted there's nothing to do...
if (empty($list))
{
return;
}
static $_used = array();
$out = '';
// Write the opening list tag
$out .= "<ul>\n";
foreach ($list as $link)
{
if (in_array($link->id, $_used))
{
continue;
}
$out .= '<li><a href="/function/' . $link->id . '">' . $link->text . '</a>';
foreach ($list as $_link)
{
if ($link->id == $_link->parent_id)
{
$sub_list[] = $_link;
}
}
if (!empty($sub_list))
{
$out .= _build_menu_tree($sub_list);
}
$out .= "</li>\n";
$_used[] = $link->id;
}
// Write the closing list tag
$out .= "</ul>\n";
return $out;
}
Array
{
[stdClass Object] =>
[id] => 2
[pid] => 1
}I read this thread, and am wondering what I'm missing that makes this so difficult. I read the description of the problem, and here's what I came up with in 10 minutes:
<?php
// Store starting time.
$start = microtime(true);
// Made up array of items from database.
$items = array(
(object) array('id' => 1,
'parent_id' => false,
'position' => 1,
'url' => 'http://www.google.com',
'title' => 'Item #1'),
(object) array('id' => 2,
'parent_id' => 1,
'position' => 3,
'url' => 'http://www.google.com',
'title' => 'Item #2'),
(object) array('id' => 3,
'parent_id' => 1,
'position' => 1,
'url' => 'http://www.google.com',
'title' => 'Item #3'),
(object) array('id' => 4,
'parent_id' => 3,
'position' => 1,
'url' => 'http://www.google.com',
'title' => 'Item #4'),
(object) array('id' => 5,
'parent_id' => 1,
'position' => 2,
'url' => 'http://www.google.com',
'title' => 'Item #5'),
(object) array('id' => 6,
'parent_id' => false,
'position' => 3,
'url' => 'http://www.google.com',
'title' => 'Item #6'),
(object) array('id' => 7,
'parent_id' => false,
'position' => 2,
'url' => 'http://www.google.com',
'title' => 'Item #7')
);
// Method for use with usort to sort items by position.
function sort_by_position($item_a, $item_b) {
if ($item_a->position == $item_b->position) return 0;
return ($item_a->position < $item_b->position) ? -1 : 1;
}
// Method for use with usort to sort items by parent_id.
function sort_by_parent_id_and_position($item_a, $item_b) {
if ($item_a->parent_id == $item_b->parent_id) {
if ($item_a->position == $item_b->position) return 0;
return ($item_a->position < $item_b->position) ? -1 : 1;
}
return ($item_a->parent_id < $item_b->parent_id) ? -1 : 1;
}
// Recursive function to create <ul>-based dropdown menu.
function menu($items, $parent_id = false) {
// Find all items at this level.
$items_at_this_level = array();
foreach ($items as $i) {
if ($i->parent_id == $parent_id) $items_at_this_level[] = $i;
elseif ($i->parent_id > $parent_id) continue;
}
// Return false if no items were found.
if (count($items_at_this_level) == 0) return false;
// Sort the items.
usort($items_at_this_level, 'sort_by_position');
// Initialize a string to store the HTML for this level.
$this_level = '<ul>';
// For each item at this level...
foreach ($items_at_this_level as $item) {
// Create the hyperlink.
$link = '<a href="' . $item->url . '">' . $item->title . '</a>';
// Create the list item for this item.
$this_level .= '<li>' . $link . menu($items, $item->id) . '</li>';
}
// Return the markup for this level.
return "$this_level</ul>";
}
// Prepare the array of menu items.
usort($items, 'sort_by_parent_id_and_position');
// Print the menu markup.
echo(menu($items));
// Store ending time.
$end = microtime(true);
// Print elapsed time.
echo($end - $start . ' seconds to complete function.');
?>As far as I can tell, it does absolutely everything you're looking for (and more) except for actually make the database call. Any comments?
If you're wondering what I meant by "and more", I added a Rails-style position column for sorting the menu items at each level. I haven't seen any of the other solutions to this problem on this thread address that issue, but I think it's pretty important. I also added the stupid microtime() stuff to (very basically) test the efficiency of this script, and it seems pretty fast to me (knowing that the biggest bottleneck, database access, isn't there). Finally, I also presorted the main array to increase efficiency (although I don't know that the efficiency gain makes up for the time spent sorting the array).
P.S. For those of you who've seen my other posts, you know that I prefer Rails to PHP… this is a great illustration of why. This would take about 5 code statements with Rails.
1 to 22 of 22