I am developing a content management system and I have run into an issue with child-parent relationships of items in the CMS.
Basically I have a system that can create pages and when a page is created you can select a parent page for sub-navigation. This is all fine and dandy until I try to generate the navigation from the DB.
I'm not sure if some sort of join would be better but I prefer to get all the data in an array and manipulate the array with php.
My array of results from the DB is like this:
Array
(
[0] => Array
(
[id] => 27
[name] => home
[link] => home.html
[parent] => 0
)
[1] => Array
(
[id] => 30
[name] => about
[link] => about.html
[parent] => 27
)
)
I need to loop through an array like this that can have any number of navigation and intelligently sort it into its parent child relationships. I was able to do it but only one level deep. It needs to manage children with children with children etc. with an infinite number of layers and output it to HTML unordered nested lists.
<ul>
<li>
<a>Nav</a>
<ul>
<li>
<a>Subnav</a>
<ul>
<li>
<a>Sub Sub nav</a>
</li>
</ul>
</li>
</ul>
<li>
<ul>
Etc. ...
I don't think you should get into objects. Plus I think it would just be extra work to generate objects and etc. In my opinion you should loop through the array and generate a multidimensional array that represents the navigational hierarchy and then loop the generated array recursively to generate your HTML. I've done a sample code for you, it works the way you want it to but you probably want to make some changes.
functions
// Generate your multidimensional array from the linear array
function GenerateNavArray($arr, $parent = 0)
{
$pages = Array();
foreach($arr as $page)
{
if($page['parent'] == $parent)
{
$page['sub'] = isset($page['sub']) ? $page['sub'] : GenerateNavArray($arr, $page['id']);
$pages[] = $page;
}
}
return $pages;
}
// loop the multidimensional array recursively to generate the HTML
function GenerateNavHTML($nav)
{
$html = '';
foreach($nav as $page)
{
$html .= '<ul><li>';
$html .= '<a href="' . $page['link'] . '">' . $page['name'] . '</a>';
$html .= GenerateNavHTML($page['sub']);
$html .= '</li></ul>';
}
return $html;
}
** sample usage **
$nav = Array
(
Array
(
'id' => 27,
'name' => 'home',
'link' => 'home.html',
'parent' => 0
),
Array
(
'id' => 30,
'name' => 'about',
'link' => 'about.html',
'parent' => 27
)
);
$navarray = GenerateNavArray($nav);
echo GenerateNavHTML($navarray);
You can probably do both things in one step but I think it's neater to generate the multidimensional array first. Goodluck!
Saad Imran's solution works alright except for if you would like multiple navigation items in the same list. I had to change a few lines to get it to generate validated list of items. I also added indents to make generated code more readable. I'm using spaces but this can be easily changed to tabs if you prefer, just replace 4 spaces with "\t"
. (note you must use double quotes, not single quotes, otherwise php doesn't replace with a tab character but actually a \t)
I am using this in codeigniter 2.1.0 with superfish (PHP5)
function GenerateNavHTML($nav, $tabs = "")
{
$tab=" ";
$html = "\n$tabs<ul class=\"sf-menu\">\n";
foreach($nav as $page)
{
//check if page is currently being viewed
if($page['link'] == uri_string()) {
$html .= "$tabs$tab<li class=\"current\">";
} else {
$html .= "$tabs$tab<li>";
}
$html .= "<a href=\"$page[link]\">$page[name]</a>";
//Don't generate empty lists
if(isset($page['sub'][0])) {
$html .= $this->GenerateNavHTML($page['sub'], $tabs.$tab);
}
$html .= "</li>\n";
}
$html .= $tabs."</ul>\n";
return $html;
}
I was getting (switched to ol for clarification)
1. Home
1. About Us
1. Products
1. sub-product 1
1. sub-product 2
1. Contact
now i get
1. Home
2. About Us
3. Products
1. sub-product 1
2. sub-product 2
4. Contact
Nicely generated HTML
<ul class="sf-menu">
<li class="current"><a href="index.html">Home</a></li>
<li><a href="about.html">About Us</a></li>
<li><a href="products.html">Products</a>
<ul class="sf-menu">
<li><a href="products-sub1.html">sub-product 1</a></li>
<li><a href="products-sub2.html">sub-product 2</a></li>
</ul>
</li>
<li><a href="contact.html">Contact</a></li>
</ul>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With