I am attemptting to attach a small CMS to a website I am creating. However I have come across a small problem. The CMS uses PHP functions for inserting menus, these PHP func
It appears Topbit already beat me to this, but mine is slightly differs in that it doesn't echo the value straight to the output stream, but saves it in a variable that you may echo
at your convenience:
<?php
function GenerateMenu($arr)
{
$output = "<ul>\n";
foreach($arr as $val) {
if (is_array($val)) {
$output .= "<li>\n" . GenerateMenu($val, $output) . "</li>\n";
}
else {
$output .= "<li>" . $val . "</li>\n";
}
}
$output .= "</ul>\n";
return $output;
}
$html = GenerateMenu($menu);
?>
Edit:
Thanks Gumbo and Topbit, now that I'm on my machine with PHP installed, I have tested it and it works fine.
A simple function is all you need.
function unorderedList($val)
{
if (is_array($val)) {
return '<ul><li>' .
implode('</li><li>',
array_map('unorderedList', $val)) .
'</li></ul>';
} else {
return $val;
}
}
Test code:
$menu = array('Projects (Menu Level 1)',
array('Project 1 (Menu Level 2)',
'Project 2 (Menu Level 2)',
'Project 3 (Menu Level 2)'),
'News (Menu Level 1)',
'Contact (Menu Level 1)');
echo unorderedList($menu);
This would be a excellent example of the use of recursion. An array (with sub-arrays within it) defines each level, and a function loops, calling itself whenever it finds a new array to process. As long as the function cleans up appropriately (closing the </li> & </ol>
), it's largely automatic.
<?php
// I know which function I'd rather write....
$tree = array('Projects (Menu Level 1)',
array('Project 1 (Menu Level 2)',
'Project 2 (Menu Level 2)',
'Project 3 (Menu Level 2)'),
'News (Menu Level 1)',
'Contact (Menu Level 1)');
// now quake beneath the power of this fully operational recursive function!
function olLiTree($tree)
{
echo '<ul>';
foreach($tree as $item) {
if (is_array($item)) {
olLiTree($item);
} else {
echo '<li>', $item, '</li>';
}
}
echo '</ul>';
}
olLiTree($tree); // kick off from the top level
I think this outputs the correct HTML structure.
function GenerateMenu($arr)
{
foreach($arr as $val) {
if (next($arr)) { $nextitem = current($arr); }
if (is_array($val)) {
$output .= "\n<ul>\n" . GenerateMenu($val, $output) . "</ul>\n</li>\n\n";
}
elseif (is_array($nextitem)) { $output .= "<li>" . $val; }
else { $output .= "<li>" . $val . "</li>\n"; }
}
return $output;
}
$html = GenerateMenu($menu);
echo("<ul>\n" . $html . '</ul>');
Same test code as above:
$menu = array('Projects (Menu Level 1)',
array('Project 1 (Menu Level 2)',
'Project 2 (Menu Level 2)',
'Project 3 (Menu Level 2)'),
'News (Menu Level 1)',
'Contact (Menu Level 1)');
I wrote this utilizing the PHP DOMDocument class. It will create your list as long and as deep as the list you give it using one simple and easy to follow loop. If you want it organized, just ask your database for the list sorted by title (or whatever) first. It assumes your query object data is contained in $menu_categories and it at least has properties of ->id ->parent_id & ->title (change to your needs)
$dom = new DOMDocument();
$dom->validateOnParse = true;
$dom->loadHTML("<html>");
$root = $dom->createElement('ul');
$root->setAttribute('class', 'menu');
$dom->appendChild($root);
foreach($menu_categories as $count => $category){
$pid = $category->parent_id;
$parent = $dom->getElementById('simple-li-'.$pid);
if($parent != null){
$ul = $dom->getElementById('simple-ul-'.$pid);
if($ul == null){
$ul = $dom->createElement('ul');
$ul->setAttribute('id', 'simple-ul-'.$pid);
$parent->appendChild($ul);
}
$target = $ul;
}else{
$target = $root;
}
$li = $dom->createElement('li', $category->title);
$li->setAttribute('id', 'simple-li-'.$category->id);
$target->appendChild($li);
}
echo $dom->saveHTML($root);
return;
Here's the commented version...
/**
* This is pure and simple PHP!
* @author Jamin Szczesny - Mar 2014
* Assuming you have a returned query list of related rows named...
* $menu_categories (the list can be in any order)
* and it has valid attributes of..
* ->id (category id)
* ->title (category title\name)
* ->parent_id (categories parent)
*
*/
$dom = new DOMDocument();//create a document
$dom->validateOnParse = true;//this is a must
$dom->loadHTML("<html>");//you must load some valid html
//add a root list to the dom
$root = $dom->createElement('ul');
$root->setAttribute('class', 'menu');
$dom->appendChild($root);
//loop through all of your category rows
foreach($menu_categories as $count => $category){
$pid = $category->parent_id;
$parent = $dom->getElementById('simple-li-'.$pid);
//see if we found a parent
if($parent != null){ //parent found...
//look for a ul within the parent
$ul = $dom->getElementById('simple-ul-'.$pid);
//check to see if that ul exists
if($ul == null){//ul not created yet so create one
$ul = $dom->createElement('ul');
$ul->setAttribute('id', 'simple-ul-'.$pid);
$parent->appendChild($ul);
}
$target = $ul;
}else{ //no parent found...
$target = $root;
}
//create this list item
$li = $dom->createElement('li', $category->title);
$li->setAttribute('id', 'simple-li-'.$category->id);
$target->appendChild($li);
}
//output only the html from our list
echo $dom->saveHTML($root);
return;