Folder & Subfolder Structure for Navigation with PHP [duplicate] - php

I am trying to add a dynamic recursive navigation list menu to a site of am working on.
The scenerio is that the menu has 2 levels related by a parentid(preid).
My issue is that I can display the 1st level list correctly, however I cannot get the second level to display properly. I am not sure where to add the UL and /UL tags for the second level.
This is what I am after
<ul>
<li>Item 1</li>
<li>item 2</li>
<li>item 3</li>
<ul>
<li>sub item 1</li>
<li>sub item 2</li>
</ul>
<li>Item 4</li>
<li>item 5</li>
<ul>
<li>sub item 1</li>
<li>sub item 2</li>
</ul>
<li>item 6</li>
</ul>
This is actually what i am getting with the below code:
<ul>
<li>item 1
<ul>
</ul>
</li>
<li>item 2
<ul>
<li>sub item 1</li>
<ul>
</ul>
<li>sub item 2</li>
<ul>
</ul>
</ul>
</li>
<li>Sports Injuries
<ul>
</ul>
</li>
</ul>
</li>
</ul>
Below is the class file I am using to create the menu:
class Dynamic_Menu
{
function getConfig()
{
$this->DB_SERVER = 'localhost';
$this->DB_USER = '***';
$this->DB_PASS = '***';
$this->DB_NAME = '***';
}
function __construct()
{
$this->getConfig();
$Conn = mysql_connect($this->DB_SERVER, $this->DB_USER, $this->DB_PASS);
if (!$Conn)
die("Error: ".mysql_errno($Conn).":- ".mysql_error($Conn));
$DB_select = mysql_select_db($this->DB_NAME, $Conn);
if (!$DB_select)
die("Error: ".mysql_errno($Conn).":- ".mysql_error($Conn));
}
function select_row($sql)
{
//echo $sql . "<br />";
if ($sql!="")
{
$result = mysql_query($sql) or die("Error: ".mysql_errno().":- ".mysql_error());
if ($result)
{
while($row = mysql_fetch_array($result))
$data[] = $row;
}
return $data;
}
}
function recordCount($sql)
{
if ($sql!="")
{
$result = mysql_query($sql) or die("Error: ".mysql_errno().":- ".mysql_error());
if ($result)
{
$cnt = mysql_num_rows($result);
return $cnt;
}
}
}
function getChild($id)
{
$menu = "";
$str = "";
$s = "SELECT * FROM vcms_sys_explorer WHERE preid = '$id' ";
$res = $this->select_row($s);
$menu .= '<ul>';
for ($i=0;$i<count($res);$i++)
{
$cnt_of_child = $this->recordCount("SELECT * FROM vcms_sys_explorer where preid = '".$res[$i][eid]."' ");
//if ($cnt_of_child > 0)
// $str = '';
//else
// $str = " (is sub menu item)";
$menu .= '<li>'. $res[$i][name].$str.'</li>';
$menu .= $this->getChild($res[$i][eid]);
}
$menu .= '</ul>';
return $menu;
}
function getMenu($parentid)
{
$menu = "";
$s = "SELECT * FROM vcms_sys_explorer WHERE preid = '$parentid' ";
$res = $this->select_row($s);
$menu .= '<ul>';
for ($i=0;$i<count($res);$i++)
{
$menu .= '<li>'.$res[$i][name].$this->getChild($res[$i][eid]).'</li>';
if ((count($res) - 1) > $i) {
}
}
$menu .= '</ul>';
return $menu;
}
}
I call the menu with:
$menu = new Dynamic_Menu();
$menu->getMenu(1);
Could someone please help and explain where I need to place the level 2 UL and /UL tags. I have been banging my head with this for the last 2 days.
Any help would be greatly appreciated, thanks...

In a nested list, sub-lists will always be contained within a list element-- that's what makes them nested. You can print a full list in just one function using this format (in generic code, but you should get the basic idea):
function get_list($parent) {
$children = query('SELECT * FROM table WHERE parent_id = '.$parent);
$items = array();
while($row = fetch_assoc($children)) {
$items[] = '<li>'.$row['name'].get_list($row['id']).'</li>';
}
if(count($items)) {
return '<ul>'.implode('', $items).'</ul>';
} else {
return '';
}
}
And this will give you a list structured properly as:
<ul>
<li>Item 1</li>
<li>Item 2
<ul>
<li>Item 2.1</li>
<li>Item 2.2</li>
</ul>
</li>
</ul>

All though this question is not the exact same as the question I posted 2 days ago, here is the result of what I was attempting to do with folders rather than a DB. The following will traverse the directory and all sub directories of the specified $path and spits out the results in a nested un-ordered list upon completion of running the script. Hope it helps.
<?php
function readDirs($path){
$dirHandle = opendir($path);
echo "<ul>";
while ($item = readdir($dirHandle)) {
$newPath = $path . "/" . $item;
if (is_dir($newPath) && $item != '.' && $item != '..') {
echo "<li><a href='$newPath'>$item</a>";
readDirs($newPath);
}
}
echo "</li></ul>";
}
$path = "./galleries";
readDirs($path);
?>

Related

Split menu list in two every 7 items

I got a dynamic menu that uses bootstrap, but one menu button has about 14 child items. Way too long for a website, so I want to split it in half.
This is the code that I'm trying to replicate:
<ul class="dropdown-menu dropdown-menu-large row" role="menu">
<li class="col-sm-6">
<ul>
<li>Life Insurance</li>
<li>Home Insurance</li>
<li>Travel Insurance</li>
<li>Pet Insurance</li>
</ul>
</li>
<li class="col-sm-6">
<ul>
<li>Boat Insurance</li>
<li>Auto Insurance</li>
<li>Bike Insurance</li>
<li>Business Insurance</li>
</ul>
</li>
</ul>
This is what I tried:
$tel = 1;
foreach ( $nmenuccr as $cmenu ) {
// If id matches and category id is 11 (services) split in half
if ( $cmenu['id'] && $cmenu['catid'] == '11' ){
if($tel == 1) {
$hmenu .= '<li class="col-sm-6"><ul>';
}
$hmenu.= '
<li>'.$cmenu['title'].'</li>
';
if(($tel % 7) == 0){
$hmenu .= '</ul></li> <li class="col-sm-6"><ul>';
}
$tel++;
if(($tel % 7) != 0){
$menu .= '</li>';
}
//Else use the normal dropdown layout
}else{
if (strlen($cmenu['title']) > 25){
$shortstrmen = substr($cmenu['title'], 0, 25) . '...';
$hmenu.= '
<li>'.$shortstrmen.'
';
}else{
$hmenu.= '
<li>'.$cmenu['title'].'
';
}
}
}
However this returns the following code:
https://jsfiddle.net/sms16v44/
Does anyone see what I am doing wrong?
Instead of trying to alter your code, I came up with the following. This allows you to automatically create sub menu's out of a menu. I hope it helps out.
It creates it like the following screenshot:
and the other function/way:
<?php
// recreating dummy menu data
function createDummyList() {
$nmenuccr = array();
for($i=0;$i<24;$i++) {
$a = array();
$a['id']=$i;
$a['catid']=$i;
$a['alias']="alias $i";
$a['title']="title $i";
array_push($nmenuccr, $a);
}
return $nmenuccr;
}
/**
* Parse a menu into smaller menu's
* #param type $menu the main menu
* #param type $class html class
* #param type $max_sub_items max items before creating a new submenu
* #param type $submenu (used for recursion)
* #return string
*/
function createMenuList(&$menu, $class, $max_sub_items) {
$out = "<ul class='$class'><li>";
// shift items
$submenu = array();
$i=0;
$loop=0;
while(count($menu) > 0) {
array_push($submenu, array_shift($menu));
$i++;
if ($i == $max_sub_items || count($menu) == 0) {
$out .= createList($submenu, $loop);
$out .= '<li>In between</li>';
$i=0;
$submenu = array();
$loop++;
}
}
$out .= "</li></ul>";
return $out;
}
/**
*
* #param type $list
* #param type $submenu_label
* #return string
*/
function createList(&$list, $loop) {
$out = '<ul>';
foreach($list as $l) {
$out .= '<li>'.$l['title'].'</li>';
}
$out .= '</ul>';
return $out;
}
/**
* Parse a menu into smaller menu's
* #param type $menu the main menu
* #param type $class html class
* #param type $max_sub_items max items before creating a new submenu
* #param type $submenu (used for recursion)
* #return string
*/
function createSubMenuList(&$menu, $class, $max_sub_items, $submenu = 0) {
// create new list
$out = "<ul class='$class'>";
// shift items
for($i=0;$i<$max_sub_items;$i++) {
$item = array_shift($menu);
// add item to list
if (isset($item)) {
$out .= '<li>'.$item['title'].'</li>';
}
}
// check if we're done
if (count($menu) > 0) {
$submenu++;
$out .= "<li class='submenu_$submenu'>";
// create submenu in parent menu
$out .= createSubMenuList($menu, $class, $max_sub_items, $submenu);
$out .= "</li>";
}
$out .= "</ul>";
return $out;
}
// call menu creation function
$list1=createDummyList();
$list2=createDummyList();
echo createSubMenuList($list1, 'hoofdmenu', 7);
echo "<hr />";
echo createMenuList($list2, 'hoofdmenu', 7);
?>
It would be easier to help if you could include the output array as comment too.
However, try this. Change this:
if(($tel % 7) != 0){
$menu .= '</li>';
}
to:
if(($tel % 7) != 0){
$menu .= '</ul></li>';
}
Hopefully it will work
Keepin it a junky piece of code, you can just quick-fix it this way:
$tel = 0;
/* .. */
// If id matches and category id is 11 (services) split in half
if ( $cmenu['id'] && $cmenu['catid'] == '11' ){
if(++$tel == 1) {
$hmenu .= '<li class="col-sm-6"><ul>';
}
$hmenu.= '<li>'.$cmenu['title'].'</li>';
if(($tel % 7) == 0){
if ($tel == 7) {
$hmenu .= '</ul></li><li class="col-sm-6"><ul>';
} else {
$hmenu .= '</ul></li>';
}
}
//Else use the normal dropdown layout
} // ..
Working example (updated):
http://sandbox.onlinephpfunctions.com/code/13fd6974cd66c847747f44a4be9b892aa47e4979
But you should refactor your $nmenuccr through a function, which will make it an array reflecting the target structure of menu to KISS the view-generating part of code.
Edit: updated operations on $tel.
Try this for any length of menu.....
<ul class="dropdown-menu dropdown-menu-large row" role="menu">
<?php
$counter = 1;
foreach ($nmenuccr as $cmenu ) {
if($counter == 1){
echo '<li class="col-sm-6"><ul>';
}//.... end of if() .....//
echo '<li>'.$cmenu['title'].'</li>';
$counter ++;
if($counter == 5){
echo "</ul></li>";
$counter = 1;
}//.... end of if() .....//
}//.... end of foreach() .....//
?>
</ul>
Your check for category ID 11 didn't seem pertinent to your question, so I didn't include that logic in there. Things become a lot simpler when you leave the opening and closing parts outside the loop. Then, you're only outputting your repeated item, and checking for the one case ($tel % 4) where you put a divider in.
<?php
$nmenuccr = [ // sample data
["alias"=>"life-insurance", "title"=>"Life Insurance"],
["alias"=>"life-insurance", "title"=>"Home Insurance"],
["alias"=>"life-insurance", "title"=>"Travel Insurance"],
["alias"=>"life-insurance", "title"=>"Pet Insurance"],
["alias"=>"life-insurance", "title"=>"Boat Insurance"],
["alias"=>"life-insurance", "title"=>"Auto Insurance"],
["alias"=>"life-insurance", "title"=>"Bike Insurance"],
["alias"=>"life-insurance", "title"=>"Business Insurance"],
];
$hmenu = "<li class=\"col-sm-6\">\n\t<ul>\n";
foreach ($nmenuccr as $tel=>$cmenu) {
if ($tel % 4 == 0 && $tel > 0) {
$hmenu .= "\t</ul>\n</li>\n<li class=\"col-sm-6\">\n\t<ul>\n";
}
$hmenu.= "\t\t<li>$cmenu[title]</li>\n";
}
$hmenu .= "\t</ul>\n</li>";
echo $hmenu;
Output:
<li class="col-sm-6">
<ul>
<li>Life Insurance</li>
<li>Home Insurance</li>
<li>Travel Insurance</li>
<li>Pet Insurance</li>
</ul>
</li>
<li class="col-sm-6">
<ul>
<li>Boat Insurance</li>
<li>Auto Insurance</li>
<li>Bike Insurance</li>
<li>Business Insurance</li>
</ul>
</li>

Highlight currenct open menu item using php

I am trying to highlight currently open menu item using PHP.
HTML for my menu items.
<ul class="menu">
<li>Edit Profile</li>
<li>Edit Contact</li>
<li>Edit Facilities</li>
<li>Edit Location</li>
<li>Manage Images</li>
</ul>
This is how I tried it in PHP:
if ($_SERVER['QUERY_STRING']) {
list($queryString) = explode('&',$_SERVER['QUERY_STRING']);
$openPage = $queryString;
list($key, $value) = explode('=',$openPage);
$currentPage = $value;
// Determine what menu item to be highlight:
switch ($currentPage) {
case 'edit-profile':
$class1 = 'class="active"';
break;
case 'edit-contact':
$class2 = 'class="active"';
break;
case 'edit-facilities':
$class3 = 'class="active"';
-----------
// Default is to include the main page.
default:
$class = 'class=""';
break;
} // End of main switch.
} else {
//Determine The Index page
$path = $_SERVER['PHP_SELF'];
$indexPage = basename($path);
$indexPage = basename($path, '.php');
}
This is how I echo these classes in my menus:
<li <?php if(isset($class1)) echo $class1; ?>>Edit Profile</li>
<li <?php if(isset($class2)) echo $class2; ?>>Edit Contact</li>
This is solution is working for me. But my problem is, if I have lot of pages I need to use many class variables in SWITCH case.
Can anybody tell me is there alternative solution for this to minimize my PHP code?
Hope somebody may help me out.
Thank you.
One simple solution would be to store the menu items in a map, and iterate over them:
$menuItems = [
'edit-profile' => [
'url' => 'index.php?p=edit-profile&error=message',
'name' => 'Edit Profile'
],
'edit-contact' => [
'url' => 'index.php?p=edit-contact',
'name' => 'Edit Contacts'
],
...
]
Then iterate over the items.
<ul class="menu">
<?php
foreach($menuItems as $menuItem => $desc) {
// You get $currentPage from the query string
$class = ($currentPage === $menuItem)? 'class="active"': '';
echo '<li '.$class.'>'.$desc['name'].'</li>';
}
?>
</ul>
With this you don't need SWITCH case.
<li <?php if($currentPage=='edit-profile') echo 'class="active"'; ?>>Edit Profile</li>
<li <?php if($currentPage=='edit-contact') echo 'class="active"'; ?>>Edit Contact</li>
You can use array and try like this
if ($_SERVER['QUERY_STRING']) {
list($queryString) = explode('&',$_SERVER['QUERY_STRING']);
$openPage = $queryString;
list($key, $value) = explode('=',$openPage);
$currentPage = $value;
// Determine what menu item to be highlight:
// Store in array, you will be having only one item in array
$class[$currentPage] = 'class="active"';
} else {
//Determine The Index page
$path = $_SERVER['PHP_SELF'];
$indexPage = basename($path);
$indexPage = basename($path, '.php');
}
and the menu can be
<li <?php if(isset($class['edit-profile'])) echo $class['edit-profile']; ?>>Edit Profile</li>
<li <?php if(isset($class['edit-contact'])) echo $class['edit-contact']; ?>>Edit Contact</li>
Note: this not tested, as I have no access to PHP right now.
Rather than doing all this, just take all your menu items in an array and loop over it.
You are sending page parameter with variable.
So, instead have a control over it while sending itself.
Array of page will have page title as key and page url as value.
This way, you do not need separate variables, single variable in loop will serve the job.
<?php
$pages = array(); // Get all page titles and urls in array.
$pages['Edit Profile'] = 'edit-profile&error=message';
$pages['Edit Contact'] = 'edit-contact';
$pages['Edit Facilities'] = 'edit-facilities';
$pages['Edit Location'] = 'edit-location';
$pages['Manage Images'] = 'edit-images';
if (! empty($pages)) {
$current = (isset($_GET['p'])) ? $_GET['p'] : '';
?>
<ul>
<?php
foreach ($pages as $title => $url) {
$active = ($current == $url) ? 'active' : '';
?>
<li><?php echo $title;?></li>
<?php
}
?>
</ul>
<?php
}
?>
Use PHP to generate your own menu structure but for highlighting we can use Jquery.
See example below:
<style>
.active{ background-color:#3F6}
</style>
<ul class="menu">
<li>Home</li>
<li>Edit Profile</li>
<li>Edit Contact</li>
<li>Edit Facilities</li>
<li>Edit Location</li>
<li>Manage Images</li>
</ul>
<script type='text/javascript' src='//code.jquery.com/jquery-1.11.0.js'></script>
<script>
var aurl = window.location.href; // Get the absolute url
$('.menu li a').filter(function() {
return $(this).prop('href') === aurl;
}).parent('li').addClass('active');
</script>

PHP Nested foreach loop, how to affect (parent?)

I have a nested foreach loop running through categories in a database. When the user is viewing a category the category ID is set and that menu item gets it's class set as "active".
The issue I'm having is when a user is viewing a subcategory, I still need it's PARENT to be set to active.
// Run through category ID's and output info
foreach ($GLOBALS['AKB_CLASS_HELPER']->tree->nodesByPid[$catid] as $rowid) {
$row = $GLOBALS['AKB_CLASS_HELPER']->catsById[$rowid];
//Check to see if user has access
if (($accessible_cats !== false) && (!in_array($row['categoryid'],$accessible_cats)) && ($row['security'] == "private")) {
continue;
}
// If we're viewing a category, output "active" as a class in the menu
if (isset($GLOBALS['CategoryId'])
&& ($GLOBALS['CategoryId']) == $row['categoryid']) {
$activeCat = "active";
} else {
$activeCat = "";
}
//Pass through global variables
$GLOBALS['Link'] = GetUrl('category', $row['categoryid']);
$GLOBALS['Text'] = $GLOBALS['AKB_CLASS_TEMPLATE']->DisablePlaceholders(strip_tags($row['name']));
$GLOBALS['Active'] = $activeCat;
$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('CategoryRowCell');
//If subcategories exist
if (isset($GLOBALS['AKB_CLASS_HELPER']->tree->nodesByPid[$rowid])
&& is_array($GLOBALS['AKB_CLASS_HELPER']->tree->nodesByPid[$rowid])
&& !empty($GLOBALS['AKB_CLASS_HELPER']->tree->nodesByPid[$rowid])) {
$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('CategoryGridHeaderSub');
//For every subcategory, output data
foreach ($GLOBALS['AKB_CLASS_HELPER']->tree->nodesByPid[$rowid] as $subrowid) {
$subrow = $GLOBALS['AKB_CLASS_HELPER']->catsById[$subrowid];
//Here's the part I can't get working. Need to output "active" to the PARENT id($row I believe)
if (isset($GLOBALS['CategoryId'])
&& ($GLOBALS['CategoryId']) == $subrow['categoryid']) {
$activeCat = "active";
} else {
$activeCat = "";
}
//Set Global Variables
$GLOBALS['Link'] = GetUrl('category', $subrow['categoryid']);
$GLOBALS['Text'] = $GLOBALS['AKB_CLASS_TEMPLATE']->DisablePlaceholders(strip_tags($subrow['name']));
$GLOBALS['Active'] = $activeCat;
$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('CategoryRowCellSub');
}
}
$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('CategoryGridFooterSub');
}
So the part I need to figure out is in the nested foreach loop, how can I affect the parent ID or something of the like.
Current Output when viewing parents(Working perfectly)
<li class="categoryItem active">Parent 1
<ul class="categorySubList">
<li class="categorySubItem"><a class="categorylink" href="/categories/Parent+1/Subcategory+1/">Subcategory 1</a></li>
<li class="categorySubItem "><a class="categorylink" href="/categories/Parent+1/Subcategory+2/">Subcategory 2</a></li>
</ul>
Current Output when viewing children(not working)
<li class="categoryItem">Parent 1<!--this list item needs to be active-->
<ul class="categorySubList">
<li class="categorySubItem active"><a class="categorylink" href="/categories/Parent+1/Subcategory+1/">Subcategory 1</a></li>
<li class="categorySubItem "><a class="categorylink" href="/categories/Parent+1/Subcategory+2/">Subcategory 2</a></li>
</ul>

Using recursion to build navigation

I'm building navigation for a site and for the life of me I can't figure out recursion. I have all my data stored via MySQL using this design:
I've read several links on how recursion works and I must be slow because it's difficult for me to grasp. I've tried to write something and I know it is not even close to what I really need, but it's a start:
PDO
public function viewCategories()
{
$viewSQL = "SELECT * FROM categories";
try
{
$pdo = new PDO('mysql:host=localhost;dbname=store','root','');
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$categoryVIEW = $pdo->prepare($viewSQL);
$categoryVIEW->execute();
$array = $categoryVIEW->fetchAll(PDO::FETCH_ASSOC);
$categoryVIEW->closeCursor();
$json = json_encode($array);
return $json;
}
catch(PDOexception $e)
{
return $e->getMessage();
exit();
}
}
Recursion
$return = json_decode($category->viewCategories(),true);
function buildNavigation($json)
{
foreach($json as $item)
{
if($item['category_id'] === $item['parent'])
{
print('<li>'.$item['category_name'].'</li>');
if($item['category_id'] === $item['parent'])
{
print('<li>match'.$item['category_name'].'</li>');
buildNavigation($json);
}
}
}
buildNavigation($return);
as expected this will never enter the condition. I did try to figure this out on my own since this is a good thing to have knowledge of, but I guess it's beyond my mental capacity :(
Thanks for having a look :)
UPDATE
I know this has been answered already, but is there a way I can do this to build an associative array? I have been playing around with a function that ALMOST works for me that I got from HERE, but it adds an extra array that I do NOT want.
Method
private function buildCategories($array,$parent)
{
$result = array();
foreach($array as $row)
{
if($row['parent'] == $parent)
{
$result[$row['category_name']] = $this->buildCategories($array,$row['category_id']);
}
}
return $result;
}
$json = json_encode($this->buildCategories($array,NULL));
return $json;
I want this:
{"reloading":{"components","presses and dies","tumblers & scales","tools & accessories","shotshell reloading"}
but what I get is this:
{"reloading":{"components":[],"presses and dies":[],"tumblers & scales":[],"tools & accessories":[],"shotshell reloading":[]}
Here's an example with recursion.
function buildNavigation($items, $parent = NULL)
{
$hasChildren = false;
$outputHtml = '<ul>%s</ul>';
$childrenHtml = '';
foreach($items as $item)
{
if ($item['parent'] == $parent) {
$hasChildren = true;
$childrenHtml .= '<li>'.$item['category_name'];
$childrenHtml .= buildNavigation($items, $item['category_id']);
$childrenHtml .= '</li>';
}
}
// Without children, we do not need the <ul> tag.
if (!$hasChildren) {
$outputHtml = '';
}
// Returns the HTML
return sprintf($outputHtml, $childrenHtml);
}
print buildNavigation($items);
That script produces the following output :
<ul>
<li>Menu 1</li>
<li>Menu 2
<ul>
<li>Sub Menu 2.1</li>
<li>Sub Menu 2.2</li>
<li>Sub Menu 2.3
<ul>
<li>Sub Menu 2.2.1</li>
<li>Sub Menu 2.2.2</li>
<li>Sub Menu 2.2.3</li>
</ul>
</li>
</ul>
</li>
<li>Menu 3</li>
</ul>
I have the same above code with little bit modification, so that a user can apply different css on each level of menu, now its showing classes of sub menu like child-class1 when its in 1st sub menu , and it will show child-class2 when its in 2nd sub menu and so on...
<?php
function buildNavigation($items, $parent = NULL, $n=NULL)
{
$hasChildren = false;
if ($parent == NULL)
{
$level=0;
$outputHtml = '<ul class="parent-class">%s</ul>';
}
else
{
if($n==NULL)
{
$level=1;
}
else
{
$level=$n;
}
$outputHtml = '<ul class="child-class'.$level.'">%s</ul>';
}
$childrenHtml = '';
foreach($items as $item)
{
if ($item['parent'] == $parent) {
$hasChildren = true;
$childrenHtml .= '<li>'.$item['ptitle'].'';
$next = ++$level;
$childrenHtml .= buildNavigation($items, $item['pageid'],$next);
$childrenHtml .= '</li>';
}
}
// Without children, we do not need the <ul> tag.
if (!$hasChildren) {
$outputHtml = '';
}
// Returns the HTML
return sprintf($outputHtml, $childrenHtml);
}
echo buildNavigation($ppages);
?>
it will show out put like this
<ul class="parent-class">
<li>
page 1
<ul class="child-class1">
<li>
this is child page
<ul class="child-class2">
<li>
child of child </li>
</ul>
</li>
</ul>
</li>
</ul>
I would like to thanks Mr #Maxime Morin.

php mysql vertical menu

I am trying to design a dynamic vertical menu :
my table is:
primary // primary key
pid //parent id 0 if none
cid //the actual category id
comment //some comment
the thing is that I want to design a php function where after reading the values from database it should output it into an html ordered list (like a multilevel nested unordered list)
I know that it would be easily achieved by using a recursion function
the problem is that i just can't do it.. I've tried many times but failed in vain
The main problem comes in nesting (where to give list items and where to start the list)
I would be very grateful if anyone of you could help me out...
well i've managed to write an ugly code:
{here i ve used two tables one for the parent and one for the child}
$query="SELECT * FROM parentCat";
$result=mysql_query($query);
echo "<ul id=\"suckertree1\">";
while($row=mysql_fetch_array($result))
{
$name=$row['comment'];
$pid=$row['catid'];
echo "<li> $name ";
$query="select * from childCat WHERE pid=$pid";
$subresult=mysql_query($query);
$af=mysql_num_rows($subresult);
if($af>0)
{
echo "<ul>";
while($subrow=mysql_fetch_array($subresult))
{
$name=$subrow['comment'];
echo "<li> $name </li>";
}
echo "</ul>";
}
echo "</li>";
}
echo "</ul>";
it will show only one sublevel...
wht should i do to make it work for infinite level
I thing a while script is best for you
$query = mysql_query("SELECT * FROM menu ORDER BY primary ASC");
$parent=0;
$sub=0
echo "<ul>";//start list
while($menu = mysql_fetch_array($query){
if($parent != $menu['pid']){//if not seen item before
if($sub != 0){echo "</ul>";}else{$sub++;}//if not first submenu, close submenu before. If first sub sub++.
echo "<ul>";}//open submenu
echo "<li>".$menu[cid]."</li>";//echo item
if($parent != $menu['pid']){//if not seen before
$parent = $menu['pid']; //set to seen before so next loop will be recognised
}
}
echo "</ul>"; //end list
I dont know if this is gonna work since I did not test it, but it should show you an option on how it could be done. Idea of lists:
<ul>
<li>Item1</li>
<ul>
<li>Subitem1</li>
<li>Subitem2</li>
</ul>
<li>Item 2</li>
<ul>
<li>Subitem1 of Item2</li>
</ul>
</ul>
Gives:
Item1
Subitem1
Subitem2
Item2
Subitem1 of Item2
Try this, it should do the trick.
<?php
$query = "SELECT a.comment parent
, b.comment child
FROM menu a
JOIN menu b
ON a.primary = b.pid
ORDER BY a.primary";
$result = mysql_query($query);
$parent = '';
echo "<ul>";
foreach ($result as $next) {
if ($next['parent'] != $parent) {
if (strlen($parent) > 0) {
echo " </ul>";
echo " </li>";
}
echo " <li>" . $next['parent'];
echo " <ul>";
}
echo " <li>" . $next['child'] . "</li>";
$parent = $next['parent'];
}
echo " </ul>";
echo " </li>";
echo "</ul>";
?>
To render a nested list for an assoc array try this:
<?php
$list = array(
'item-1' => 'test-1',
'item-2' => 'test-2',
'item-3' => array(
'item-3-1' => 'test-3',
'item-3-2' => array(
'item-3-2-1' => 'test-4',
'item-3-2-2' => 'test-5',
),
),
'item-4' => 'test-6',
);
function render_list($list) {
echo '<ul>';
foreach ($list as $key => $value) {
echo '<li>';
echo $key.':';
if (is_array($value)) render_list($value);
else echo $value;
echo '</li>';
}
echo '</ul>';
}
render_list($list);
Which will result in this:
<ul>
<li>item-1:test-1</li>
<li>item-2:test-2</li>
<li>
item-3:
<ul>
<li>item-3-1:test-3</li>
<li>
item-3-2:
<ul>
<li>item-3-2-1:test-4</li>
<li>item-3-2-2:test-5</li>
</ul>
</li>
</ul>
</li>
<li>item-4:test-6</li>
</ul>
item-1:test-1
item-2:test-2
item-3:
item-3-1:test-3
item-3-2:
item-3-2-1:test-4
item-3-2-2:test-5
item-4:test-6

Categories