I'm beginner and I'm trying to make a simple navigation menu with a dropdown but the first loop stops when the nested loop is completed. Is there any suggestion? Please be analytic because of my low programming skills.
<?php
function nav_main($dbc, $path) {
$q = "SELECT * FROM navigation ORDER BY position ASC";
$r = mysqli_query($dbc, $q);
while($nav = mysqli_fetch_assoc($r)) {
$nav['slug'] = get_slug($dbc, $nav['url']);
if($nav['parent_id'] == 0) {
?>
<li<?php selected($path['call_parts'][0], $nav['slug'], ' class="active"') ?>><?php echo $nav['label']; ?></li>
<?php
}
elseif ($nav['parent_id'] == 1) {
?>
<li class="dropdown<?php selected($path['call_parts'][0], $nav['slug'], ' active"') ?>"><?php echo $nav['label']; ?><span class="caret"></span>
<ul class="dropdown-menu">
<?php
while($subnav = mysqli_fetch_assoc($r)) {
$subnav['slug'] = get_slug($dbc, $subnav['url']);
if($subnav['parent_id'] == 3) {
?>
<li><?php echo $subnav['label']; ?></li>
<li role="separator" class="divider"></li>
<?php
}
}
?>
</ul>
</li>
<?php
}
}
}
?>
Both your while loops are processing the same result set!
So obviously when the second while loop finishes the resultset is completely consumed and there is nothing left for the outer while look to do but terminate.
This is a precise of what you are doing :-
$q = "SELECT * FROM navigation ORDER BY position ASC";
$r = mysqli_query($dbc, $q);
// first while loop
while($nav = mysqli_fetch_assoc($r)) {
// inner while loop
while($subnav = mysqli_fetch_assoc($r)) {
Both are using $r and therefore regardless of you using a different variable to hold the returned row data the inner loop will consume row 2->end of the same result set as is being processed in the outer while loop
Related
Ive been building a data driven website displaying general info about countries in the world. Its been made so that 1 country is displayed per page and you can move the next country by clicking a pagination link. Only problem that I am having is I cannot limit the amount of visible links. I did try this for loop with the first line as this: for ($i = $Page; $i <= min($Page + 9, $TotalRecords); $i++) { which does reduce it to the 10 records however this does result in the website breaking when I test the web address by entering index.php?page=aa.
<nav class="mt-5">
<ul class="pagination pagination-lg justify-content-center">
<?php
if( isset($Page) ) {
if ($Page > 1 ) {
?>
<li class="page-item">
«
</li>
<?php
}
}
?>
<?php
global $ConnectingDB;
$sql = "SELECT COUNT(*) FROM countriesinfo";
$stmt = $ConnectingDB->query($sql);
$RowPagination = $stmt->fetch();
$TotalRecords = array_shift($RowPagination);
$RecordPagination = $TotalRecords / 1;
$RecordPagination = ceil($RecordPagination);
for ($i = $Page; $i <= $RecordPagination; $i++) {
if( isset($Page) ) {
if ($i == $Page)
{
?>
<li class="page-item active">
<?php echo $i; ?>
</li>
<?php
} else {
?>
<li class="page-item">
<?php echo $i; ?>
</li>
<?php
}
}
}
?>
<?php if (isset($Page) && !empty($Page) ) {
if ($Page+1 <= $RecordPagination) {
?>
<li class="page-item">
»
</li>
<?php
}
}
?>
</ul>
</nav>
I test the web address by entering index.php?page=aa.
You can check to make sure the get variable is a number by using php is_numeric() bulit in function
and if it isn't force it to number 1.
This will stop the website from breaking when someone manipulate the page varible.
Here is a code to help you out, put at the beginning of the page.
if(is_numeric($page)){
$page = $page; // if $page is a number do nothing
}else{
$page = 1; //else set $page to 1 which will fetch data from beginning
}
Problem: One piece (That we can identify currently) is causing a clients product list to call the database over and over again (3600 times) at points when loading a longer list of products.
Code:
<?php foreach ($cats as $cat) :
if (in_array($cat->getId(), [68, 28, 27, 59, 79, 80, 119])) :
$cat_show = Mage::getModel('catalog/category')->load($cat->getId());
$children = $cat_show->getChildrenCategories($cat->getId());
$url1 = $cat_show->getURL();
$showAnyways = in_array(strtolower($cat_show->getName()), ["hats", "juniors", "accessories"]);
if ($cat_show->getShowSidebar() == 1 || $showAnyways) : ?>
<li class="current<?php if ($cat->getId() == $current_cat) { ?> active <?php } ?>">
<?php echo $cat->getName() ?>
<ul>
<?php if ($cat_show->getID() != 68 && $cat_show->getID() != 59) { ?>
<li class="current<?php if ($cat->getId() == $current_cat && $j == 0) {
$j++; ?> active<?php } ?>"><a class="view_all" href="<?php echo $url1 ?>"><?php echo $this->__("View All"); ?></a></li>
<?php } ?>
<?php foreach ($children as $subcat) {
$subcat_show = Mage::getModel('catalog/category')->load($subcat->getId());
if ($subcat_show->getShowSidebar() == 1 || in_array($subcat_show->getID(), [84])) {
$grand_children = Mage::getModel('catalog/category')->getCategories($subcat->getId());
if ($grand_children) {
$cats_displayed = 0;
foreach ($grand_children as $grand_child) {
$grand_child_show = Mage::getModel('catalog/category')->load($grand_child->getId());
if ($grand_child_show->getShowSidebar() == 1) {
$url = Mage::getModel('catalog/category')->load($grand_child_show->getId())->getURL();
?>
<li class="current<?php if ($grand_child->getId() == $current_cat && $j == 0) {
$j++; ?> active<?php } ?>">
<?php echo $grand_child_show->getName() ?>
</li>
<?php $cats_displayed++;
}
}
}
if ($cats_displayed == 0 || !$grand_children) {
$url = Mage::getModel('catalog/category')->load($subcat->getId())->getURL();
?>
<li class="current<?php if ($subcat->getId() == $current_cat && $j == 0) {
$j++; ?> active<?php } ?>">
<?php echo $subcat->getName() ?>
</li>
<?php }
}
} ?>
</ul>
</li>
<?php endif;?>
<?php endif;?>
<?php endforeach; ?>
Can anyone provide me with some pointers on how to make this FAR more efficient and not make so many DB calls.
Should note, I am not an amazing php developer by trade. Main language is python so I am trying to get some advice on the best way to go about fixing this given my less that great knowledge of php itself.
You should never have a database query call inside a for loop. You need to build a query at the start that will get all the data required before the for loop.
Some instant pointers I can see are:
$grand_child_show = Mage::getModel('catalog/category')->load($grand_child->getId());
if ($grand_child_show->getShowSidebar() == 1) {
$url = Mage::getModel('catalog/category')->load($grand_child_show->getId())->getURL();
This is calling the database twice for no reason, you should be able to do this:
$grand_child_show = Mage::getModel('catalog/category')->load($grand_child->getId());
if ($grand_child_show->getShowSidebar() == 1) {
$grand_child_show->getURL();
You should be able to drop all these 'GetModel' functions if at the start of the script you call something like:
$all_grand_children = Mage::getModel('catalog/category')->getAllCategories();
This would return a hash array which you would be able to access relevant items by doing the following inside the for loop:
$grand_children = $all_grand_children[$subcat->getId()];
This would replace
$grand_children = Mage::getModel('catalog/category')->getCategories($subcat->getId());
You should also do a initial call for all of the grand_child and cat_show objects. If you are skilled at SQL you can call just the relevant information by joining the tables in one SQL query.
Here Is my question: What I am wanting To do is Take Results from a mysql table and turn them into a menu and a drop down menu
HERE IS A QUICK EXAMPLE:
if you see in my mysql table i have page_name and parent, So the example is:
page_name and if i have row 1 the page_name is 'Home' now it's parent is 'none' right but on id number 39 the page_name is 'Contact Us' and the Parent Is 'Far Far Away 123' so if the parent is equal to 'none' then it will show at the top of the menu not the drop down if it has a parent it will show under that parent like this:
Home | the ben page | The Brock Page | Far Far Away 123 | dsfk
Contact Us
You see Contact Us is under Far Far Away Because the parent Is Far Far Away 123
here is my table:
Here is my code That I am trying but it is not working for some reason:
<ul>
<?php
$sql = "SELECT * FROM pages ORDER by item_order";
$result = mysqli_query($db, $sql);
confirm_query($result);
while ($links = mysqli_fetch_assoc($result)) {
if($links['parent'] !== "none") {
?>
<li id = "<?php echo $links['id']; ?>"><a href="
<?php
echo "page.php?id=" . $links['id'] . "\" title=\"" . $links['page_title'] . "\"";
?>>
<?php
echo $links['page_name'];
?>
</a>
<?php
if($links['parent'] !== "none") {
$child = "";
$sql = "SELECT * FROM pages";
$result = mysqli_query($db, $sql);
while($row = mysqli_fetch_assoc($result)) {
if($row['parent'] !== "none") {
$child = $row['page_name'];
}
}
echo "<ul id=\"sub_menu\" class=\"sub_navagation" . $links['id'] . "\">";
echo "<li>";
echo $child;
echo "<li>";
echo "</ul>";
}
?>
</li>
<?php
}
}
?>
</ul>
CSS:
#sub_menu {
display: none;
}
#sub_menu:hover {
display: block;
}
Ok if as you can see i have the parent row in the MYSQL table and on id number 39 i want the 'Far Far Away123' to be the parent of Contact Us and i want to show it when i hover over 'Far Far Away123'
My suggestion is to build out an array of all the results. Then run through that array (instead of multiple database queries).
I added a function build_dropdown() that will take the page name and run through the array of pages to see if there are any items with a parent matching. If so, we make an array of those items and run through them to build the dropdown menu. If not, it does nothing and moves on to the next menu item.
<?php
function build_dropdown ($parent, $pages){
foreach($pages as $page){
if($page['parent'] == $parent){
$items = $page;
} // END if
} // END foreach
if(is_array($items)){ // If a sub
echo '<ul id="sub_menu" class="sub_navagation'. $item['id'] .'">';
foreach($items as $item){
echo '<li>'.$item['name'].'<li>';
} // END foreach
echo '</ul>';
} // END if
}
$sql = "SELECT * FROM pages ORDER by item_order";
$result = mysqli_query($db, $sql);
confirm_query($result);
while ($row = mysqli_fetch_assoc($result)) {
$pages[] = $row; // Add each row to $pages array to use later
}
foreach($pages as $key => $page){
if($page['parent'] == 'none'){ ?>
<li id = "<?php echo $page['id']; ?>">
<a href="page.php?id=<?php echo $page['id']; ?>" title="<?php echo $page['page_title']; ?>">
<?php echo $page['page_name']; ?>
</a>
<?php
build_dropdown($page['page_name'], $pages); // If there are child items then build them out
?>
</li>
<?php
} // END if
} // END foreach
?>
I suggest you will need to JOIN your table to basically query it again to get the parent value, and add that to your markup.
SELECT *
FROM Pages
LEFT JOIN Pages p2 on page_name = p2.parent
(note: the syntax above may not be right, but I wanted to give you an idea of where I would start).
I have two lists (1 and 2) and I want to update them when an item is moved from one to another.
HTML:
<ul class="sortable" id="task-list">
<li id="listItem_1">Value 1 </li>
<li id="listItem_2">Value 2 </li>
<li id="listItem_3">Value 3 </li>
</ul>
<ul class="sortable" id="task-list-two">
<li id="listItem_4">Value 1 </li>
<li id="listItem_5">Value 2 </li>
<li id="listItem_6">Value 3 </li>
</ul>
JS:
$("#task-list, #task-list-two").sortable({
handle : '.handle',
connectWith: ".sortable"
update : function () {
var order = $('#task-list').sortable('serialize');
$("#info").load("process-sortable.php?"+order);
}
});
But I want to update the list (1 or 2) as well. Do I need to post an additional variable to process.sortable.php ?
The foreach I currently have is only for the first list (simplified):
$task = nl2br($_POST['task']);
$userid = $_SESSION['userid'];
$position = $_POST['p'];
$date = $_POST['date'];
$i = "INSERT INTO tasks VALUES('','$task','$userid','0','$position','$date')";
$doi = mysql_query($i) or die(mysql_error());
Thanks in advance!
UPDATED FOREACH PHP:
foreach ($_GET['listItem'] as $position => $item)
{
$list = $_GET['list'];
if($list == "task-list")
{
$list = 1;
}
if($list == "task-list-two")
{
$list = 2;
}
$sql = "UPDATE `tasks` SET `position` = $position AND date = '$list' WHERE `id` = $item";
print($sql);
$dosql = mysql_query($sql) or die(mysql_error());
}
You could just pass the lists id to the PHP page like:
$("#info").load("process-sortable.php?"+order+"&list="+$(this).attr('id'));
Once on the PHP page, you can make a condition for the list type.
You will also need to change the order variable to account for the different lists:
var order = $(this).sortable( "serialize" );
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