PHP Pagination Display - php
I'm using bootstrap pagination, and a combination PHP/mysql method of displaying my results, (ex. results.php?results=1 for each page). This is working fine, but actually displaying the pagination div at the bottom of my page, i.e. which one is active, whether or not you can click the following or preceding items (if there actually are results on those pages)
So I've done a specific case for just about every combination I could think of that would affect anything, but it is certainly not efficient. Can anyone suggest a better way to do it? Some of the cases will be obvious, like if I'm on page one, I don't want to show page 0 and -1 in the pagination, others are less obvious, like if I'm on page 3, and there are no more pages, I want page 3 to be in the middle, as there are 5 numbers displayed, but you should not be able to click on 4 and 5.
I'm using an exact replica of the plugin showed here except I've added left and right increase / decrease by one in addition to the first / last page.
<div id="pagination" style="width: 340px; margin-left: auto; margin-right: auto;">
<? if ($results == 1) { ?>
<ul class="pagination">
<li class="disabled"> <i class="fa fa-lg fa-angle-double-left"></i> </li>
<li class="disabled"> <i class="fa fa-lg fa-angle-left"></i> </li>
<li class="active"><? echo $results; ?> <span class="sr-only">(current)</span></li>
<li <?if ($num_rows < $num_res) { echo "class=\"disabled\""; } ?>><? echo $results + 1; ?></li>
<li <?if ($num_rows < ($num_res * 2)) { echo "class=\"disabled\""; } ?>><? echo $results + 2; ?></li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>><? echo $results + 3; ?></li>
<li <?if ($num_rows < ($num_res * 4)) { echo "class=\"disabled\""; } ?>><? echo $results + 4; ?></li>
<li <?if ($num_rows < ($num_res)) { echo "class=\"disabled\""; } ?>> <i class="fa fa-lg fa-angle-right"></i> </li>
<li <?if ($num_rows < ($num_res)) { echo "class=\"disabled\""; } ?>> <i class="fa fa-lg fa-angle-double-right"></i> </li>
</ul>
<? } ?>
<? if ($results == 2) { ?>
<ul class="pagination">
<li> <i class="fa fa-lg fa-angle-double-left"></i> </li>
<li> <i class="fa fa-lg fa-angle-left"></i> </li>
<li><? echo $results - 1; ?></li>
<li class="active"><? echo $results; ?> <span class="sr-only">(current)</span></li>
<li <?if ($num_rows < ($num_res * 2)) { echo "class=\"disabled\""; } ?>><? echo $results + 1; ?></li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>><? echo $results + 2; ?></li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>><? echo $results + 3; ?></li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>> <i class="fa fa-lg fa-angle-right"></i> </li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>> <i class="fa fa-lg fa-angle-double-right"></i> </li>
</ul>
<? } ?>
<? if (($results == 3) && (($last_page == 3))) { ?>
<ul class="pagination">
<li> <i class="fa fa-lg fa-angle-double-left"></i> </li>
<li> <i class="fa fa-lg fa-angle-left"></i> </li>
<li><? echo $results - 2; ?> </li>
<li><? echo $results - 1; ?></li>
<li class="active"><? echo $results; ?><span class="sr-only">(current)</span></li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>><? echo $results + 1; ?></li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>><? echo $results + 2; ?></li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>> <i class="fa fa-lg fa-angle-right"></i> </li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>> <i class="fa fa-lg fa-angle-double-right"></i> </li>
</ul>
<? } ?>
<? if (($results > 2) && ($results < ($last_page - 1))) { ?>
<ul class="pagination">
<li> <i class="fa fa-lg fa-angle-double-left"></i> </li>
<li> <i class="fa fa-lg fa-angle-left"></i> </li>
<li><? echo $results - 2; ?> </li>
<li><? echo $results - 1; ?></li>
<li class="active"><? echo $results; ?><span class="sr-only">(current)</span></li>
<li><? echo $results + 1; ?></li>
<li><? echo $results + 2; ?></li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>> <i class="fa fa-lg fa-angle-right"></i> </li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>> <i class="fa fa-lg fa-angle-double-right"></i> </li>
</ul>
<? } ?>
<? if (($results > 2) && ($results == ($last_page - 1))) { ?>
<ul class="pagination">
<li> <i class="fa fa-lg fa-angle-double-left"></i> </li>
<li> <i class="fa fa-lg fa-angle-left"></i> </li>
<li><? echo $results - 3; ?></li>
<li><? echo $results - 2; ?></li>
<li><? echo $results - 1; ?></li>
<li class="active"><? echo $results ?><span class="sr-only">(current)</span></li>
<li><? echo $results + 1; ?></li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>> <i class="fa fa-lg fa-angle-right"></i> </li>
<li <?if ($num_rows < ($num_res * 3)) { echo "class=\"disabled\""; } ?>> <i class="fa fa-lg fa-angle-double-right"></i> </li>
</ul>
<? } ?>
<? if (($results > 2) && ($results == $last_page) && ($results != 3)){ ?>
<ul class="pagination">
<li> <i class="fa fa-lg fa-angle-double-left"></i> </li>
<li> <i class="fa fa-lg fa-angle-left"></i> </li>
<li><? echo $results - 4; ?> </li>
<li><? echo $results - 3; ?></li>
<li><? echo $results - 2; ?></li>
<li><? echo $results - 1; ?></li>
<li class="active"><? echo $results ?><span class="sr-only">(current)</span></li>
<li class="disabled"> <i class="fa fa-lg fa-angle-right"></i> </li>
<li class="disabled"> <i class="fa fa-lg fa-angle-double-right"></i> </li>
</ul>
<? } ?>
</div>
If no one feels like helping with the first portion, I understand, it works as it is as far as I can tell.
But I also am wondering if there's a way that on my class="disabled", I can remove the hrefs? Or do I just have to put an if statement on every one? Thanks.
Edit: Based on #Scopey's recommendations. I changed a few things as I saw fit, as well as a couple variable names.
$numberOfPages = ceil($num_rows / $num_res);
$numberOfPages = (int)$numberOfPages;
$url = explode('&', $_SERVER['REQUEST_URI']);
function myFilter($string) {
return strpos($string, 'results=') === false;
}
$url = array_filter($url, 'myFilter');
$url = implode('&', $url);
?>
<ul class="pagination">
<li<?php if($results === $numberOfPages): ?> class="disabled"<?php endif; ?>><a href="<?php
if($results !== $numberOfPages){
echo $url.'&results=' . 1;
} else { echo '#'; }
?>"> <i class="fa fa-lg fa-angle-double-left"></i> </a></li>
<li<?php if($results === 1): ?> class="disabled"<?php endif; ?>><a href="<?php
if($results !== 1){
echo $url.'&results=' . ($results - 1);
} else { echo '#'; }
?>"> <i class="fa fa-lg fa-angle-left"></i> </a></li>
<?php
// Print the pagination...
// Minimum of 5 pages in the pagination, even if there aren't 5 pages...
$pageCount = ($numberOfPages < 5) ? 5 : $numberOfPages;
// Loop through from page 1 until the last page ($pageCount)
for($i = 1; $i <= $pageCount; $i++)
{
// Echo out just the beginning of the <li> tag as we don't yet
// know if this needs to be disabled...
echo '<li';
// Added to show if current page is active
if($i === $results) {
echo ' class="active"';
}
// Check if:
// - This current page is greater than the amount of pages of
// results we have
// - OR, this is the currently selected page
if($i > $numberOfPages || $results === $i)
{
// <li> tag needs the disabled class....
echo ' class="disabled"';
}
// Finish the <li> tag and start generating the link
echo '><a href="';
// Opposite logic from above... Only if this is a page we know about
// AND this is not the current page.
if($i < $numberOfPages && $results !== $i)
{
// The link will be your page, with the get param, and the
// current page number we're printing
echo $url.'&results=' . $i;
}
else
{
// Otherwise just a # (no link)
echo '#';
}
// Finish this page... Print the page number ($i)
echo '">' . $i . '</a></li>';
}
?>
<li<?php if($results === $numberOfPages): ?> class="disabled"<?php endif; ?>><a href="<?php
if($results !== $numberOfPages){
echo $url.'&results=' . ($results + 1);
} else { echo '#'; }
?>"> <i class="fa fa-lg fa-angle-right"></i> </a></li>
<li<?php if($results === $numberOfPages): ?> class="disabled"<?php endif; ?>><a href="<?php
if($results !== $numberOfPages){
echo $url.'&results=' . $numberOfPages;
} else { echo '#'; }
?>"> <i class="fa fa-lg fa-angle-double-right"></i> </a></li>
<?php
#Scobey, this works great, as intended, and same as my original post, except for a couple things. In my example, I was able to get the current page in the middle of the . For example, << 1 | 2 | 3 | 4 | 5 >>, that's why I had so many different statements with +1 and -1, +2, -2 etc.
Second, my intention was to display 5 page options at all times, not just a minimum of five. So if I was on page 6, I would only see << 4 | 5 | 6 | 7 | 8 >>, not 1-8. It may not be necessary to do it this way, it's a nice to have. But, I don't want to get to a point where I have over 50 different page numbers in the pagination.
Generally dynamic pagination works only when you have a few things
A count of all possible results (total)
An amount of results you want to show per page
The current page number
Information about the results that should appear on this page.
Imagine that you have a database table called Results that has a whole bunch of results you want on your paginated page
1. Count of all possible results
This is achievable with a simple SQL statement like:
SELECT count(*) FROM Results
2. Amount per page
This is a value you get to decide yourself.
3. The current page number
This is usually 1 by default, but when the pagination is changed, it gets passed through as a get parameter.
4. A slice of results from the table
Achievable with:
SELECT * FROM Results LIMIT 0, 20
This example retrieves the first 20 results in our results table...
5. The pagination
Now, using 20 results as a default "count per page"
$countPerPage = 20;
// Get the total number of results
$result = pg_query('SELECT count(*) FROM Results'); // I'm using PostgreSQL for this example
$totalResultCount = (int)pg_fetch_result($result, 0, 0);
// The ceil function will round floats up.
$numberOfPages = ceil($totalResultCount / $countPerPage);
// Check if we have a page number in the _GET parameters
if(!empty($_GET) && isset($_GET['page']))
{
$page = (int)$_GET['page'];
}
else
{
$page = 1;
}
// Check that the page is within our bounds
if($page < 0)
{
$page = 1;
}
elseif($page > $numberOfPages)
{
$page = $numberOfPages;
}
// Build the query for the results...
$query = 'SELECT * FROM Results LIMIT ' . ($page - 1) * $countPerPage . ', ' . $countPerPage;
$results = pg_fetch_all(pg_query($query));
// Deal with printing your results etc...
?>
<ul class="pagination">
<li<?php if($page === 1): ?> class="disabled"<?php endif; ?>><a href="<?php
if($page !== 1){
echo 'page.php?page=' . $page - 1;
} else { echo '#'; }
?>">«</a></li>
<?php
// Print the pagination...
// Minimum of 5 pages in the pagination, even if there aren't 5 pages...
$pageCount = ($numberOfPages < 5) ? 5 : $numberOfPages;
// Loop through from page 1 until the last page ($pageCount)
for($i = 1; $i < $pageCount; $i++)
{
// Echo out just the beginning of the <li> tag as we don't yet
// know if this needs to be disabled...
echo '<li';
// Check if:
// - This current page is greater than the amount of pages of
// results we have
// - OR, this is the currently selected page
if($i > $numberOfPages || $page === $i)
{
// <li> tag needs the disabled class....
echo ' class="disabled"';
}
// Finish the <li> tag and start generating the link
echo '><a href="';
// Opposite logic from above... Only if this is a page we know about
// AND this is not the current page.
if($i < $numberOfPages && $page !== $i)
{
// The link will be your page, with the get param, and the
// current page number we're printing
echo 'page.php?page=' . $i;
}
else
{
// Otherwise just a # (no link)
echo '#';
}
// Finish this page... Print the page number ($i)
echo '">' . $i . '</a></li>';
}
?>
<ul class="pagination">
<li<?php if($page === $numberOfPages): ?> class="disabled"<?php endif; ?>><a href="<?php
if($page !== $numberOfPages){
echo 'page.php?page=' . $page + 1;
} else { echo '#'; }
?>">»</a></li>
<?php
Disclaimer
I just sat here and wrote this, I have not tested it, but the general idea is there. Hopefully it makes sense. I'm running out of time and don't have time to test or improve it, but if you're interested I might fix it up later.
Hope this helps!
Related
How to set first menu active in mega menu?
I am trying to create a hoverable mega menu, all works fine except the active one. I checked in source codes and active class is added, but it doesn't show up the content until mouseenter on it. see image please : And this is when I go on it with mouse, it show up with no problem. I gues I need to set main (FINANCE is main menu in pic) menu active, but dont know how to pass it to submenu. Here is my full code : $stmt_menu = $pdo->prepare("SELECT * FROM categories WHERE parentId = ? LIMIT 5"); $stmt_menu->execute([0]); if ($stmt_menu->rowCount() > 0) { $query = $stmt_menu->fetchAll(); foreach ($query as $row) { if ($row['cat_type'] == 'mega') { ?> <li class="dropdown megamenu-fw mega-li-<?php echo $row['catId']; ?>"> <?php echo $row['catName']; ?><span class="caret"></span> <ul class="dropdown-menu megamenu-content dropdown-top" role="menu" aria-expanded="true" data-mega-ul="<?php echo $row['catId']; ?>"> <li> <?php $stmt_menu = $pdo->prepare("SELECT * FROM categories WHERE parentId = ? LIMIT 5"); $stmt_menu->execute([$row['catId']]); if ($stmt_menu->rowCount() > 0) { $subquery = $stmt_menu->fetchAll(); ?> <div class="sub-menu-left"> <ul class="nav-sub-categories"> <?php $i = 0; foreach ($subquery as $subq) { $actives = ''; if($i == 0){ $actives = ' active'; } ?> <li data-category-filter="<?php echo $subq['cat_seo_url']; ?>-<?php echo $subq['catId']; ?>" class="li-sub-category<?php echo $actives; ?>"><?php echo $subq['catName']; ?></li> <?php $i++; } ?> </ul> </div> <div class="sub-menu-right"> <?php $i = 0; foreach ($subquery as $subcats) { $actives = ''; if($i == 0){ $actives = ' active'; } ?> <div class="sub-menu-inner filter-<?php echo $subcats['cat_seo_url']; ?>-<?php echo $subcats['catId']; ?><?php echo $actives; ?>"> <div class="row row-menu-right"> <div class="col-sm-3 menu-post-item"> <div class="post-item-image"> <a href="is-allowance-instantly-strangers-applauded"> <img src="assets/img/img_bg_md.png" data-src="uploads/images/202203/image_380x226_624239afd7295.jpg" alt="Is allowance instantly strangers applauded" class="lazyload img-responsive img-post" width="1" height="1"/> </a> </div> <h3 class="title"><?php echo $subcats['cat_seo_url']; ?> Is allowance instantly strangers applauded</h3> <p class="post-meta"> admin <span>Mar 28, 2022</span> <span><i class="icon-comment"></i>2</span> <span class="m-r-0"><i class="icon-eye"></i>894</span> </p> </div> </div> </div> <?php $i++; } ?> </div> <?php } ?> </li> </ul> </li> <?php } elseif ($row['cat_type'] == 'dropdown') { echo ' <li class="nav-item"><a class="nav-link" href="' . $row["cat_seo_url"] . '">test</a></li>'; } else { echo ' <li class="nav-item"><a class="nav-link" href="' . $row["cat_seo_url"] . '">' . $row["catName"] . '</a></li>'; } } }
Page view in php
I have to make a small adjustment on a website, the problem comes on the page. For example I have a page with 11 button, these 1 I do not have to show them at once, but I have for example I have to show the first 5 and then the page has to be moving but I never have to stop showing 5 results on the page. I leave reference images: This is the way the page does NOT have to look: This is the way the page should look: for example if I get to 7 that 3 is no longer shown and shows me 8 This is my code <nav> <ul class="pagination"> <?php if ($pagina == 1) : ?> <li class="page-item disabled"> <a class="page-link" href=""> <span class="ti-arrow-left"></span> </a> </li> <?php else : ?> <li class="page-item"> <a class="page-link" href="?pagina=<?php echo $pagina - 1 ?>"> <span class="ti-arrow-left"></span> </a> </li> <?php endif; ?> <!----------------------------------------------------------------------> <?php for ($i = 1; $i <= $numeroDePaginas; $i++) { if ($pagina == $i) { echo "<li class='page-item active'> <a class='page-link' href='?pagina=$i'>$i</a> </li>"; } else { if (($i + 2) < $pagina || ($i - 2) > $pagina) { echo "<li class='page-item'> <a class='page-link' href='?pagina=$i'>$i</a> </li>"; } } } ?> <!----------------------------------------------------------------------> <?php if ($pagina == $numeroDePaginas) : ?> <li class='page-item disabled'> <a class='page-link' href=''> <span class='ti-arrow-right'></span> </a> </li> <?php else : ?> <li class='page-item'> <a class='page-link' href="?pagina=<?php echo $pagina + 1 ?>"> <span class='ti-arrow-right'></span> </a> </li> <?php endif; ?> </ul> </nav>
Here you go. I have added next_pages variable and previous_pages variables, which will make sure to get the pagina - 2 and pagina + 2 if exists. Let me know if you need help understanding it. <nav> <?php $next_pages = ($pagina + 2) <= $numeroDePaginas ? $pagina + 2 : $numeroDePaginas; $previous_pages = ($pagina - 2) >= 1 ? $pagina - 2 : 1; ?> <ul class="pagination"> <?php if ($pagina == 1) : ?> <li class="page-item disabled"> <a class="page-link" href=""> <span class="ti-arrow-left"></span> </a> </li> <?php else : ?> <li class="page-item"> <a class="page-link" href="?pagina=<?php echo $pagina - 1 ?>"> <span class="ti-arrow-left"></span> </a> </li> <?php endif; ?> <!----------------------------------------------------------------------> <?php for ($i = $previous_pages; $i <= $next_pages; $i++) { if ($pagina == $i) { echo "<li class='page-item active'> <a class='page-link' href='?pagina=$i'>$i</a> </li>"; } else { echo "<li class='page-item'> <a class='page-link' href='?pagina=$i'>$i</a> </li>"; } } ?> <!----------------------------------------------------------------------> <?php if ($pagina == $numeroDePaginas) : ?> <li class='page-item disabled'> <a class='page-link' href=''> <span class='ti-arrow-right'></span> </a> </li> <?php else : ?> <li class='page-item'> <a class='page-link' href="?pagina=<?php echo $pagina + 1 ?>"> <span class='ti-arrow-right'></span> </a> </li> <?php endif; ?> </ul> </nav> Edit with more explaination: I have added a variable called next_pages, this variable checks if the current page (ex: 9) + 2 is smaller than or equal to "numeroDePaginas" variable, I have done this to make sure that we never show any pages exceeding the number of pages we have, in case 9+2 is bigger than "numeroDePaginas" we set the variable equal to "numeroDePaginas" For the previous_pages variable, we make sure that the current page(ex: 3) - 2 is never less than 1, (so it doesn't show 0 or negative pages for example), in case 3-2 is smaller than 1, we set the variable to 1. Now, I have edited the for loop, to make sure that it starts from the previous_pages variable, and ends with next_pages variable. Here are a test case: $pagina = 7; $numeroDePaginas = 9; //$next_pages will be = 9 (i.e 7+2) //$previous_pages will be = 5 (i.e 7-2) for loop would print pages from 5 to 9.
smart PHP Pagination
I want to split pages to make it more smart and look nice, I use this code to make Pagination if (!isset($_GET['page'])){ $page = 1; } else { $page = intval($_GET['page']); } $numbershownews = 1; $x = ($page-1)*$numbershownews; $select_news_all = $mysqli->query("SELECT id FROM news where FIND_IN_SET('$id_newscats_cat', cats) order by time desc"); $num_news_all = $select_news_all->num_rows; $cn = $num_news_all/$numbershownews; $select_news = $mysqli->query("SELECT * FROM news where FIND_IN_SET('$id_newscats_cat', cats) order by time desc limit $x,$numbershownews"); while ($rows_news = $select_news->fetch_array(MYSQL_ASSOC)){ $id_news = $rows_news ['id']; $title_news = $rows_news ['title']; } i show pages by this code <? $pagenext = $page+1; $pageprev = $page-1; ?> <ul> <li> <? if (($page == 1) or ($page == "")){ ?> <i class="fa fa-angle-double-right"></i> <? }else{ ?> <a class="link" href="<? echo "{$newurltitle_newscats_cat}-c-{$id_newscats_cat}-p-{$pageprev}.html"; ?>"><i class="fa fa-angle-double-right"></i></a> <? } ?> </li> <?php for($i=0; $i<$cn; $i++){ $pagenumber = $i+1; if($page == $pagenumber){ echo "<li>{$pagenumber}</li>"; }else{ ?> <li><a class="link" href="<? echo "{$newurltitle_newscats_cat}-c-{$id_newscats_cat}-p-{$pagenumber}.html"; ?>"><? echo $pagenumber; ?></a></li> <? } } ?> <li> <? if($page >= $cn){ ?> <i class="fa fa-angle-double-left"></i> <? }else{ ?> <a class="link" href="<? echo "{$newurltitle_newscats_cat}-c-{$id_newscats_cat}-p-{$pagenext}.html"; ?>"><i class="fa fa-angle-double-left"></i></a> <? } ?> it works well but it gives me pages like this 1,2,3,4,5,6,7,8,9,10 i want to split pages like this 1,2,3,4,...,9,10 how can i do this thanks
Selecting every 3rd item starting after the 2nd
I have the following code: $loop = 0; $columns = 3; <?php while ( have_posts() ) : the_post(); $loop++; ?> <li class="<?php if ( $loop % $columns == 0) echo 'last'; if ( ( $loop - 1 ) % $columns == 0 ) echo 'first'; ?>"> </li> What I want to achieve is: <li class="first"></li> <li class="last"></li> <li class="first"></li> <li class=""></li> <li class="last"></li> <li class="first"></li> <li class=""></li> <li class="last"></li> What I am getting is (which makes sense..): <li class="first"></li> <li class="=""></li> <li class="last"></li> <li class="first"></li> <li class=""></li> <li class="last"></li> <li class="first"></li> <li class=""></li> <li class="last"></li> meaning the first 2 are given the class first and last respectively and after that it is every 3. If i was able to use css I would say nth-child(3n+2) but I can't because I want to assign a new class, and I can only assign a style with css. How can I achieve it with php?
The following will generate the code that you gave as an example: <?php $loop = 0; $offset = 2; while ($loop < 100) { echo '<li class="'; if ($loop < $offset) { if ($loop % 2 == 0) { echo 'first'; } else { echo 'last'; } } else { if (($loop - $offset) % 3 == 0) { echo 'first'; } elseif (($loop - $offset + 2 ) % 3 == 0) { echo ''; } else { echo 'last'; } } echo '"></li>'; ++$loop; } If the $loop variable is under the offset it print first and last alternately otherwise it will check divisibility with 3, giving the dividend an extra offset for each condition so they will be true sequentially.
CSS Dropdown menu through PHP, logic defeats me
My brain doesn't seem to want to work this morning.. i have the following array: private $nav_pages = [['0', 'Home', 'home'], ['0', 'About Us', 'about'], ['0', 'Our Services', 'services'], ['1', 'PROCURE TO PAY (P2P)', 'procure'], ['1', 'ORDER TO CASH (02C)', 'cash'], ['1', 'GENERAL ACCOUNTING', 'general'], ['2', 'Charting of Accounts', 'charting'], ['2', 'General Ledger Maintenance', 'maintenance'], ['2', 'Accounts Receivable Services', 'receivable'], ['2', 'Accounts Payable Services', 'payable'], ['2', 'Reconciliation of Bank Accounts and Credit Cards', 'reconciliation'], ['2', 'Preparing Financial Statements', 'statements'], ['2', 'Payroll Processing', 'payroll'], ['1', 'CLOSING & REPORTING', 'closing'], ['0', 'How It Works', 'how-it-works'], ['0', 'Contact Us','contact'], ['0', 'Careers', 'careers']]; This is then fed to a php page which is meant to lay out a multi-layered pure css drop down menu.. the php page code is: <ul class="<?php echo $ul_class; ?>"> <?php $this_layer = 0; // place array content into variables foreach ($links as $link) { $item_layer = $link[0]; $item_string = $link[1]; $item_link = $link[2]; if ($item_layer > $this_layer) { ?> <ul> <?php $this_layer++; } elseif ($item_layer == $this_layer) { ?> <li class="<?php echo $item_link; ?>"> <a class="<?php echo $item_link; ?>" href="/<?php echo $item_link; ?>"> <?php echo $item_string; ?> </a> </li> <?php } elseif ($item_layer < $this_layer) { ?> </li></ul> <?php $this_layer--; } ?> <?php } ?> The output is not correct however as the above code always closes the list item containing the second layer before the second layer is ready to be closed. if that makes sense.. <ul class="pages_nav"> <li class="home"> <a class="home" href="/home"> Home </a> </li> <li class="about"> <a class="about" href="/about"> About Us </a> </li> <li class="services"> <a class="services" href="/services"> Our Services </a> </li> <ul> <li class="cash"> <a class="cash" href="/cash"> ORDER TO CASH (02C) </a> </li> <li class="general"> <a class="general" href="/general"> GENERAL ACCOUNTING </a> </li> <ul> <li class="maintenance"> <a class="maintenance" href="/maintenance"> General Ledger Maintenance </a> </li> <li class="receivable"> <a class="receivable" href="/receivable"> Accounts Receivable Services </a> </li> <li class="payable"> <a class="payable" href="/payable"> Accounts Payable Services </a> </li> <li class="reconciliation"> <a class="reconciliation" href="/reconciliation"> Reconciliation of Bank Accounts and Credit Cards </a> </li> <li class="statements"> <a class="statements" href="/statements"> Preparing Financial Statements </a> </li> <li class="payroll"> <a class="payroll" href="/payroll"> Payroll Processing </a> </li> </li></ul> </li></ul> <li class="contact"> <a class="contact" href="/contact"> Contact Us </a> </li> <li class="careers"> <a class="careers" href="/careers"> Careers </a> </li> SOLUTION: <ul class="<?php echo $ul_class; ?>"> <?php $this_layer = 0; // place array content into variables foreach ($links as $link) { $item_layer = $link[0]; $item_string = $link[1]; $item_link = $link[2]; // check if link needs to be manipulated switch($do) { case 'strtolower': $item_string = strtolower($item_string); break; case 'strtoupper': $item_string = strtoupper($item_string); break; } ?> <?php if ($item_layer > $this_layer) { ?> <ul> <li class="<?php echo $item_link; ?>"> <a class="<?php echo $item_link; ?>" href="/<?php echo $item_link; ?>"> <?php echo $item_string; ?> </a> <?php $this_layer++; } elseif ($item_layer == $this_layer) { ?> </li><li class="<?php echo $item_link; ?>"> <a class="<?php echo $item_link; ?>" href="/<?php echo $item_link; ?>"> <?php echo $item_string; ?> </a> <?php } elseif ($item_layer < $this_layer) { ?> </li></ul></li><li class="<?php echo $item_link; ?>"> <a class="<?php echo $item_link; ?>" href="/<?php echo $item_link; ?>"> <?php echo $item_string; ?> </a> <?php $this_layer--; } ?> <?php } ?>
Never close the the li tag, close it when you add something foreach ($links as $link) { if ($item_layer > $this_layer) { echo '<ul><li> ......'; this_layer++; }elseif ($item_layer == $this_layer) { echo '</li><li>......'; }elseif ($item_layer < $this_layer) { echo '</li></ul><li>......'; $this_layer--; } } Last you probably need to add a echo '</li></ul>' outside of the foreach to close everything
Had to rework the code a little, usually i organize the php menu structure in tree form makes it easier to parse into html menus, but here it is: <ul class="<?php echo $ul_class; ?>"> <?php $this_layer = 0; $closeit = false; // place array content into variables foreach ($nav_pages as $link) { $item_layer = $link[0]; $item_string = $link[1]; $item_link = $link[2]; if ($item_layer > $this_layer) { // Changing level, dont close the previous li ?><ul><?php $closeit = false; $this_layer++; } if ($item_layer == $this_layer) { // Same level, check if you need to close previous li if ($closeit) { ?></li><?php } // Render the li ?> <li class="<?php echo $item_link; ?>"> <a class="<?php echo $item_link; ?>" href="/<?php echo $item_link; ?>"> <?php echo $item_string; ?> </a> <?php // Close it on next loop $closeit = true; } elseif ($item_layer < $this_layer) { // Changing layer back down, close the previous li and the current level ul ?> </li> </ul> <?php $this_layer--; } } // Finished loop, there should still be a li waiting to be closed if ($closeit) { ?></li><?php } // Close menu ?> </ul> Should be working, let me know if it isnt Suggested php menu structure: $menu = array( array( "url"=>"/place.php", "text"=>"Go to place" ), array( "url"=>"/place2.php", // not necessary "text"=>"with submenu", "children"=>array( array( "url"=>"/placewithinplace2.php", "text"=>"submenu item" ) ) ) );