I'm trying to create a function for a hierarchical navigational menu bar.
I want to be able to have something like this...
<ul id="navigation">
<li>Menu Item 1</li>
<li>Menu Item 2</li>
<ul>
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 1</li>
</ul>
<li>Menu Item 3</li>
<li>Menu Item 4</li>
</ul>
I'm using this function, but it's not working properly like I'd like it to. It's showing the main parent links, but not the child links.
function build_navbar($pid,$sub=0)
{
global $db;
$query = $db->simple_select("navbar", "*", "pid='".$pid."'", array("order_by" => "disporder"));
$menu_build = "<ul id=\"navigation\">\n";
while($menu = $db->fetch_array($query))
{
if($sub == 1)
{
$menu_build .= "<ul>\n";
$menu_build .= "<li>".$menu['title']."</li>\n";
$menu_build .= "</ul>\n";
}
else
{
$menu_build .= "<li>".$menu['title']."</li>\n";
}
build_navbar($menu['id'],1);
}
$menu_build .= "</ul>\n";
return $menu_build;
}
Perhaps someone can help me fix this? Thanks.
--- New Update ---
Andy Groff, this is what your code is outputting:
<ul id="navigation">
<li>Home</li>
<ul>
<li>Child Link</li>
<li>Child 2</li>
</ul>
<li>Parent</li>
</ul>
However, I need it modified so it'll output like this:
<ul id="navigation">
<li>Home
<ul>
<li>Child Link</li>
<li>Child 2</li>
</ul>
</li>
<li>Parent</li>
</ul>
This is what it is outputting now, Andy:
<ul id="navigation">
</li>
<li>Home
</li>
<ul>
<li>
Child Link
</li>
<li>Child 2
</ul>
</li>
<li>Parent
</ul>
I think your problem could have something to do with the fact that your function is recursive, but the string you're building gets reset at the top of your function each time, instead of being passed into the function again. Also, I don't see anywhere that sub will get set back to zero for your final iteration. Additionally, it seems like you shouldn't need to query for each individual row. It would be more effective to query once and build the whole menu. I think the recursion can be ditched. Also, I would recommend storing a "sub" flag in your data, instead of using some hard to understand php logic as to whether or not a given row is a sub menu. I made modifications based of these concepts, no idea if it works or not though since I don't have/want to create the data to test it:
function build_navbar()
{
global $db;
//first things first, i'd recommend putting a "sub" flag in your database. This example will use it.
//start off by getting all of the rows. No need for recursion.
$query = $db->simple_select("navbar", "*", "1", array("order_by" => "disporder"));
$menu_build = "<ul id=\"navigation\">\n";
//keep track of what level we're at
$level = 1;
while($menu = $db->fetch_array($query))
{
//get sub from data
$sub = $menu['sub']
//we need to go back to root level
if($sub == 0 && $level == 2){
$level--;
$menu_build .= "</ul></li>\n";
}
else $menu_build .= "</li>\n";
//we need to go up one level
if($sub == 1 && $level == 1)
{
$level++;
$menu_build .= "<ul><li>\n";
}
else $menu_build .= "<li>";
//always print out a link
$menu_build .= "".$menu['title']."\n";
}
$menu_build .= "</ul>\n";
return $menu_build;
}
UPDATE:
Try this:
function build_navbar($pid, $sub=0)
{
global $db;
$class = $sub ? "sub" : "navigation";
$menu_build = "<ul class=\"$class\">\n";
$query = $db->simple_select("navbar", "*", "pid='".$pid."'");
while($menu = $db->fetch_array($query))
{
$menu_build .= "<li>".$menu['title']."\n";
// build child links
$menu_build .= build_navbar($menu['id'],1);
}
$menu_build .= "</ul>";
return $menu_build;
}
What we are doing here, is allowing each function to build a <ul><li> group, the $sub variable will determine what the ID of the <ul> will be, allowing you to theme each ul differently.
EDIT:
I found it!
this line
build_navbar($menu['id'],1);
needs to be changed to this:
$menu_build = build_navbar($menu['id'],1);
It looks like it should work to me.
What I would do is add some echo statements displaying the SQL query that is being executed each time, then you can copy that into phpmyadmin (or what ever db browser you use). See if it also returns a null result. If it does, there might be something wrong with your data as well.
so for example:
echo "SELECT FROM navbar * WHERE pid='$pid' ORDER_BY disporder;<br>";
Related
I am using a bootstrap pagination menu on my website to navigate from one page to another page.
I copied the pagination menu from :
http://www.w3schools.com/bootstrap/tryit.asp?filename=trybs_pagination_active&stacked=h
and added this to all pages of my website .
It's works fine and I can set the Active Status using:
<li class="active">
1</li>
according to the page link where the code is.
For some reasons ,I want to have only one menu file and include it to all pages .
Is there a way to automatically add ".active" class to the links in included menu?
menu.php
<ul class="pagination">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
Please help!
You can do it depending on your setup. In javascript, using jQuery for example:
var currentPage = 2; //say the page is defined like this
$('.pagination li').eq((currentPage-1)).addClass('active');
If you generating pages server side, for example in PHP
$currentPage = 2;
$output = '<ul class="pagination">';
//iterating pages
if($pageNum == $currentPage){
$output .= <li><a class="active" href="pages/'+$pageNum+'.php">'+$pageNum+'</a></li>
} else {
$output .= '<li>'+$pageNum+'</li>';
}
$output .= '</ul>'
echo $output;
I want to create a menu with submenus. I created a bit of the code, and it is reading all my submenus, but I want to divide those menus in categories:
Example:
Menu - Submenu 1, submenu 2, submenu 3
How can I divide my submenus?
Here my code:
function buildMenu(){
global $ii, $array;
printMenu($ii, $array);
}
$query= ("SELECT * FROM menu INNER JOIN submenu USING(menu_id)");
$array = db_array($query, 'a+');
$ii = count($array);
Calling the function
function printMenu($ii, $array){
for ($i = 0; $i < $ii; $i++) {
$name = $array[$i]['name'];
$suburl = $array[$i]['url'];
echo "<li class='menuItem1'>". $name."</li>";
}
}
Table information:
Submenu:
submenu_id,menu_id,url,name
Menu:
menu_id,friendlyname,name
Well I think you need to wrap up your PHP code with HTML UL, LI tags. For creating sub menu items, use your php loops as necessary.
Example:
<ul id="nav">
<li class="first-child level0"><?php echo $menu_item_1;?></li>
<ul class="level0">
<li class="level1 nav-1-1 first">Sub menu 1</li>
<li class="level1 nav-1-2 last">Sub menu 2</li>
</ul>
<li class="second-child level0"><?php echo $menu_item_2;?></li>
</ul>
I am developing a website using PHP and this is the 1st time I am trying a dynamic menu.
What I am doing is I have created a table for pages.
The table structure is as follows:
____________________________________________________________________________
|page_id|title|url|content|menu_title|show_on_navuigation|is_sub|parent_page|
|_______|_____|___|_______|__________|___________________|______|___________|
Here is_sub indicates whether it is a dropdown menu of some main menu. and parent_page is the main menu of the sub menu.
Now, what I want is, like
I have created 2 parent pages:
About Us and Test
and 2 sub menu's: Test aboutus and testsub,
Test aboutus is sub of About Us and testsub is sub of test.
How actually should the query and the loop, so that the menu renders perfectly.
Thanks in advance.
This is my menu structure:
<ul>
<li class='has-sub'><a href='#'><span>About Us</span></a>
<ul>
<li><a href='corporateprofile'><span>Corporate Profile</span></a></li>
<li class='last'><a href='visionandmission'><span>Vision & Mission</span></a></li>
</ul>
</li>
<li class='has-sub'><a href='#'><span>Business Services</span></a>
<ul>
<li><a href='recruitment'><span>Recruitment</span></a></li>
<li><a href='training'><span>Training</span></a></li>
<li><a href='executivesearch'><span>Executive Search</span></a></li>
<li><a href='payroll'><span>Payroll</span></a></li>
<li class='last'><a href='backgroundverification'><span>Background Verification</span></a></li>
</ul>
</li>
<li class='has-sub'><a href='#'><span>Employers</span></a>
<ul>
<li><a href='enquiry'><span>Enquiry</span></a></li>
<li><a href='jobdescription'><span>Job Description</span></a></li>
<li><a href='employercontract'><span>Employer Contract</span></a></li>
<li class='last'><a href='feedback'><span>Feedback</span></a></li>
</ul>
</li>
<li class='has-sub'><a href='javascript:;'><span>Job Seeker</span></a>
<ul>
<li><a href='applyforjob'><span>Apply For Job/Register</span></a></li>
<li><a href='careertips'><span>Career Tips</span></a></li>
<li><a href='interview Questions'><span>Interview Questions</span></a></li>
<li><a href='interviewprocess'><span>Interview Process</span></a></li>
<li class='last'><a href='corporatedress'><span>Corporate Dress</span></a></li>
</ul>
</li>
<li class='has-sub'><a href='#'><span>Franchise</span></a>
<ul>
<li class='last'><a href='#'><span>Franchise Enquiry Form</span></a></li>
</ul>
</li>
<li class='last'><a href='#'><span>Contact us</span></a></li>
</ul>
<?php
function displayMenu($parent_page_id) {
$sql = "SELECT * FROM `pages` WHERE `parent_page` = '$parent_page_id'"; // sql
$result = mysql_query($sql);
if( mysql_num_rows($result) === 0 ) { // mysql_num_rows() is deprecated, but you are using mysql extension so that's why I show it here
return true; // exit function
} // else, continue to rest of function
echo '<ul>';
while($row = mysql_fetch_assoc($result)) { // deprecated mysql php function here for simplicity
echo '<li>' . $result['menu_title'] . ''; // no closing </li> yet
displayMenu($row['page_id']); // this is the recursive part
echo '</li>'; // close the <li> from before the recursion
}
echo '</ul>';
}
$get_base_menu = mysql_query("SELECT * FROM pages WHERE parent_page = 0");
while($fetch_base_menu = mysql_fetch_array($get_base_menu))
{
$parent_page_id = $fetch_base_menu['page_id'];
displayMenu($parent_page_id);
}
?>
I highly suggest trying to get away from using an Adjacency List model and move toward a much easier to manage solution, such as a nested set. Using an MPTT type solution should help you manage your hierarchical data much easier. Using an Adjacency List model you are limited at a certain point.
I'd suggest looking into using something along the lines of Zebra_MPTT, or some other form of MPTT library. Please checkout this article on Managing Hierarchical data in MySQL.
I think the simplest thing for you to code will be something like this recursive function. All you have to do is put it on your page and make sure you have parent_page_id = 0 for the base level menu items. (I'm using parent_page_id instead of parent_page because I assume that is what you mean and it is more clear for the answer.)
Calling the function with an argument of "0" should give you the full menu tree.
$trace = array();
function displayMenu($parent_page_id) {
$sql = "SELECT * FROM `tbl_menu` WHERE `parent_page_id` = $parent_page_id"; // sql
$result = mysql_query($sql);
if( mysql_num_rows($result) === 0 ) { // mysql_num_rows() is deprecated, but you are using mysql extension so that's why I show it here
$trace[] = "Page_id $parent_page_id has no children";
return true; // exit function
} // else, continue to rest of function
echo '<ul>';
while($row = mysql_fetch_assoc($result)) { // deprecated mysql php function here for simplicity
$trace[] = "Entered while loop for page_id = $parent_page_id"; // not an error, just tracking
echo '<li>' . $row['menu_title'] . ''; // no closing </li> yet
displayMenu($row['page_id']); // this is the recursive part
echo '</li>'; // close the <li> from before the recursion
}
echo '</ul>';
}
displayMenu(0); // call function for base level
var_dump($trace);
More info:
I have researched the topic before and had a nice link to a page on mysql.com with an in-depth exploration of hierarchical relational database structures. But when I checked, the link was broken!
But, I think I found it on another site, here:
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
I need help to display a list of entries in an unordered list from a database. The problem I have now is how to loop through the array of data coming from the database to display in groups of say tens.
So the first ten categories will display in the first .
And subsequent categories also displayed in their respective s.
Eg.
<ul>
<li>Category 1 Item 1</li>
<li>Category 1 Item 1</li>
... ......................... . .......
<li>Category 1 Item 10</li>
</ul>
<ul>
<li>Category 2 Item 1</li>
<li>Category 2 Item 1</li>
... ......................... . .......
<li>Category 2 Item 10</li>
</ul>
Any help will greatly be appreciated. Thanks
echo("<ul>");
$count = 0;
while(...fetch next row...) {
if($count % 10 == 0)
echo("</ul><ul>");
echo("<li>" . $catName . "</li>");
$count++;
}
echo("</ul>");
The problem I have now is how to loop
through the array of data coming from
the database to display in groups of
say tens.
How are your categories organized in your row? I'm going to assume you have a single "category" column that you're trying to organize by. AND that you've sorted it in the query by using ORDER BY.
Then assuming you have an array of these sorted rows, you can just track when the category changes
$currCat = "NotaNumber";
$output = "";
while ($row = mysql_fetch_row($queryRes))
{
# when the category changes, add closing and opening ul's
# we'll trim the excess </ul> and <ul> off later
# You can change this to also limit the number printed
# by combining with the other answer
if ($row['categoryColumn'] != $currCat)
{
$output .= "</ul>";
$output .= "<ul>";
$currCat = $row['categoryColumn'];
}
$output .= "<li> Category No: " . $row['categoryColumn'] .
" Data:" . $row['catData'] . "</li>";
}
# Trim </ul> from front and <ul> from back by getting a substring
$output = substr($output, 5, strlen($output) - 9);
echo $output
Original answer
Printing categories organized as array of arrays:
function printCategories($catItems)
{
echo "<ul>";
$numPrinted = 0;
foreach ($catItems as $catItem)
{
echo "<li> $catEntry </li>"
$numPrinted++;
if ($numPrinted > 10)
{
break;
}
}
echo "</ul>";
}
foreach ($categories as $category)
{
printCategories($category);
}
There's a lot of PHP tags in there, but I'm assuming you'll use this in your view so you're going to have HTML to fill it out in any case.
<?php $i = 0; ?>
<?php foreach($categories as $catgory) : ?>
<?php if ($i == 0) : ?>
<ul>
<?php endif; ?>
<li>$catgory</li>
<?php if ($i == 9) : $i = 0 ?>
</ul>
<?php endif; ?>
<?php $i++; ?>
<?php endforeach ?>
Use PHPTAL
$categories = array_chunk($categories, 10);
$tal = new PHPTAL;
$tal->categories = $categories;
$html = <<<HTML
<ul tal:repeat="category categories">
<li tal:repeat="item category">
Category ${repeat/category/number}
Item ${repeat/item/number}
</li>
</ul>
HTML;
$tal->setSource($html, __FILE__);
echo $tal->execute();
I really dig the idea of using a recursice function to build my site menus but I am having a problem and have been banging my head for ages now.
I need my menu function to return a nested list but I dont want non-active irelevent elements of the tree to be displayed.
Details. I have a MySql database with a table called menu_items that stores all of the usual fields for a nav item (target, link_text, title, etc) as well as a unique id for each item and importantly a parent_id.
This is all up for debate though, for instance would it be easier to store this information in an XML file?
For example here is an example menu with all elements shown:
<ul>
<li>link 1
<ul>
<li>link 1-1
<li>link 1-2
</ul>
</li>
<li>link 2
<ul>
<li>link 2-1
<li>link 2-2
</ul>
</li>
<li>link 3</li>
</ul>
But if the current page is for example 1-2.html I want to have a menu like this:
<ul>
<li>link 1
<ul>
<li>link 1-1
<li>link 1-2
</ul>
</li>
<li>link 2</li>
<li>link 3</li>
</ul>
Evidently I would pass either the ID or the name of the current page to the Menu function.
Any ideas anyone?
I have been banging my head against a wall for some time now :-)
This is my complete method where the databse has a page id, a parent id, a link (permalink) and a title; hope it helps.
function make_nav($current_page_id)
{
nav_rec(0, $current_page_id, constant('SITE_URL'), 0);
}
function nav_rec($page, $current_page_id, $link, $level)
{
if (!$page)
{
$page = array();
$page['page_id'] = '0';
}
else
{
?><a class="nav-link nav-level-<?= $level ?>" href="<?= $link ?>"><?= $page['title'] ?></a><?
}
// Checks for the subpages from this page.
$page_q = "
SELECT id AS page_id, parent_id, permalink, page_title AS title
FROM ".constant('MYSQL_PREFIX')."pages
WHERE `page_type` = 'page'
AND `in_nav` = '1'
AND `status` = 'published'
AND `is_deleted` = '0'
AND `parent_id` = '".$page['page_id']."'";
if ($page_rs = mysql_query($page_q))
{
if (mysql_num_rows($page_rs))
{
while($page = mysql_fetch_assoc($page_rs))
{
nav_rec($page, $current_page_id, $link . $page['permalink'].'/', $level+1);
}
}
else
{
$level = 0;
}
}
else
{
$level = 0;
}
}