Bootstrap drop-down menu using PHP and MySQL - php

I am new to PHP. With Laravel this is simple:
#isset($tags)
#foreach($tags as $tag)
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true">
{{ $tag->name }}
</a>
<ul class="dropdown-menu">
#foreach($tag->categories as $category)
<li><a href="{{-- route('register') --}}" {{$category->name }}</a></li>
<li class="divider"></li>
#endforeach
</ul>
</li>
#endforeach
#endisset
I need to use plain PHP as Laravel seems to slow considerably and I did this
<?php if(isset($tags)): ?>
<?php foreach($tags as $tag): ?>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true">
<?php echo $tag['name'] ?>
</a>
</li>
<?php endforeach ?>
Now I am stuck.
The $tags display quite alright but I don't seem to get $tag->categories to dropdown.
this how my query looks like:
SELECT t.id, t.name as tag_name, c.id, c.name as c_name from tags t INNER JOIN category_tag ct ON (t.id = ct.tag_id)'.
'INNER JOIN categories c ON (ct.category_id = c.id) ORDER BY t.id
Any help would be nice.

Try this:
<?php
if(isset($tags)){
foreach($tags as $tag){ ?>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true">
<?php echo $tag->name; ?>
</a>
<ul class="dropdown-menu">
<?php
foreach($tag->categories as $category){ ?>
<li><a href="{{route('register')}}" <?php echo $category->name; ?> </a></li>
<li class="divider"></li>
<?php } ?>
</ul>
</li>
<?php }
}
?>
Although, i would recommend using laravel syntax. it wont make your page slower because the are just helpers that are translated to something like the above example.

No dropdown seems normal, cause you don't have <ul class="dropdown-menu"> in your php script, like the one mentioned in your laravel blade:
<ul class="dropdown-menu">
#foreach($tag->categories as $category)
<li><a href="{{-- route('register') --}}" {{$category->name }}</a></li>
<li class="divider"></li>
#endforeach
</ul>
However, as you said, in laravel it is simple, cause of Eloquent Model relationships.
Of course, you can do it, in vanilla php in many different ways.
These 2 approaches came up my mind...
Fetch categories in second query and align them to your $tag in foreach.
Rebuild your query and add sub queries, to add concatenated column, which can be parsed by php.
Please note that, the first one uses more php processing, whilest the second one, causes much more load on database.
Let's focus on the second one, with mixed database processing and php...
So lets modify your query to:
SELECT t.id, t.name as tag_name,
(SELECT group_concat(
(SELECT concat_ws(':',c.id,c.name) FROM categories c WHERE ct.category_id = c.id)
) FROM category_tag ct WHERE ct.tag_id = t.id) as categories_ctn
from tags t ORDER BY t.id
Now you will have a column categories_ctnwith concatenated data separated by , with category_id:category_name
So the last thing to do, is to explode your data to arrays and modify your view script. Please note comments in this php script...
<?php if(isset($tags)): ?>
<?php foreach($tags as $tag) { ?>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true">
<?php echo $tag['tag_name'] ?>
</a>
<ul class="dropdown-menu">
<?php
$categories = explode(',',$tag['categories_ctn']);
foreach($categories as $category_data) {
$category = explode(':',$category_data);
?>
<li><a href="#<?php echo $category[0]; // here you get category id ?>" <?php echo $category[1]; // here you get category name ?></a></li>
<li class="divider"></li>
<?php } ?>
</ul>
</li>
<?php } ?>
I hope that now you have a grasp, of what you can receive from mysql query, and what you can do with that data in php.
I have not tested the code, but it should work straight away.
Thoughtful thought, do you use Laravel or not?
Cause in Laravel all mentioned above is pointless, and you can achieve the same result really simple, via Model relationships, like in the blade you mentioned...
The code mentioned above is portable, meaning you can use it in any php project, and I believe this is what your question was...
Second thought...
Remember that joining categories in mysql, will bring you one of categories instead of all...
This example is about showing all categories for tag in your menu...
And finally don't avoid Laravel, cause it is beauty one of a kind... :)

Related

How I can make drop down menu from my categories mysql table only show if parent_id is not 0

So hey there as the title said I am looking for away to make my categories with subcategories. I been looking in stackoverflow for what I need but none has help me of the examples..
Here is how my table look like
So I know what I want and what I need but I have no idea how I can do that possible
I have to SELECT * FROM categories ORDER by position ASC
I have to check if parent_id is bigger then 0.
I have to remove the parent_id from my navbar and show them only under the category name where it should be by dropdown menu .
But I have no idea how I could do all of that ..
Here is how I am selecting only my categories and display them
$catsq = mysqli_query($con,"SELECT * FROM categories ORDER by position ASC");
while($catinfo=mysqli_fetch_assoc($catsq)) {
echo '
<li class="nav-item'.(isset($_GET["cat"]) && $_GET["cat"]==$catinfo["id"] ? " active" : "").'">
<a class="nav-link" href="./index.php?cat='.$catinfo["id"].'">'.$catinfo["name"].'</a>
</li>
';
}
and it's look like this
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link" href="cat=1">TestCat</a>
</li>
<li class="nav-item">
<a class="nav-link" href="cat=2">TestCat2</a>
</li>
<li class="nav-item">
<a class="nav-link" href="cat=3">TestSub</a>
</li>
</ul>
but I want It to look like this
<ul class="nav navbar-nav">
<li class="">TestCat</li>
<li class="dropdown ">
//TestCat2 have to doing nothing always.
TestCat2</i>
<ul class="dropdown-menu">
<li><a class="nav-link" href="cat=3">TestSub</a></li>
</ul>
</li>
</ul>
when the parent_id is more then 0..
If anyone can help me with this would be great..
Thanks to everybody.
There are several approaches you can take:
Build an array
Nested queries
Recursion
Array
This approach builds a data structure that you can iterate through in your view. Working example
<?php
// get db connection...
// create categories array
$stmt = mysqli_query($con, "SELECT * FROM categories ORDER BY position ASC");
while( $row = mysqli_fetch_assoc($stmt)) {
// $category[ $row['parent_id] ][ $row['id'] ] = $row; // use if you need to access other fields in addition to name
$category[ $row['parent_id] ][ $row['id'] ] = $row['name'];
}
// other php stuff...
?>
<html>
... snip ...
<ul class="nav navbar-nav">
<?php foreach($category[0] as $id => $name): ?>
<?php if( isset( $category[$id]) ): ?>
<li class="dropdown ">
<?= $name ?>
<ul class="dropdown-menu">
<?php foreach($category[$id] as $sub_id => $sub_name): ?>
<li><a class="nav-link" href="?cat=<?= $sub_id ?>" ><?= $sub_name ?></a></li>
<?php endforeach; ?>
</ul>
</li>
<?php else: ?>
<li class="">
<?= $name ?>
</li>
<?php endif; ?>
<?php endforeach; ?>
</ul>
Nested Queries
This method is easiest to display using an imaginary class that does all the sql stuff behind the scenes. For the sake of argument, we will assume a class Category that has a method named listByParent($parent_id) which returns a list of rows having the designated parent_id.
<?php
$cat = new Category();
$topLevel = $cat->listByParent(0);
?>
<html>
... snip ...
<ul class="nav navbar-nav">
<?php foreach( $topLevel as $topRow ): ?>
<!-- note, this method is run on every iteration of top level categories -->
<?php $subRows = $cat->listByParent($topRow['id']) ?>
<?php if( count($subRows)): ?>
<li class="dropdown ">
<?= $topRow['name'] ?>
<ul class="dropdown-menu">
<?php foreach($subRows as $row): ?>
<li><a class="nav-link" href="?cat=<?= $row['id'] ?>" ><?= $row['name'] ?></a></li>
<?php endforeach; ?>
</ul>
</li>
<?php else: ?>
<li class="">
<?= $topRow['name'] ?>
</li>
<?php endif; ?>
<?php endforeach; ?>
</ul>
Recursion
Using recursion would allow you to have “unlimited” levels of subcategories. However, it’s a level of complexity that does not seem warranted in this case. But should you want to pursue it, note that the best way to approach it would be to make a template for the html that could be accessed programatically, with $cat->findByParent() being a key player...

Categories are repeating for each subcategory

I am showing categories in Menu. Some categories have subcategories.
function for getting parent categories
function get_parent_category(){
$query="select * from blog_categories where parent_id=0
ORDER BY
CASE id
WHEN '2' THEN 1
WHEN '1' THEN 2
WHEN '3' THEN 3
ELSE id
END";
$rows=array();
$result=$this->query($query);
while($row=$this->fetch_array($result)){
$row['url']=$this->get_cat_url($row);
$rows[]=$row;
}
return $rows;
}
Function for subcategories
function get_child_category(){
$query="select * from blog_categories where parent_id!=0";
$rows=array();
$result=$this->query($query);
while($row=$this->fetch_array($result)){
$row['url']=$this->get_cat_url($row);
$rows[]=$row;
}
return $rows;
}
Showing on the page like this:
<ul class="nav navbar-nav">
<li>Home</li>
<?php
foreach($this->parent_category as $cat){
foreach($this->child_category as $child_cat){
if($cat['id']==$child_cat['parent_id']){
?>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#"><?php echo $cat['name'];?>
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><?php echo $child_cat['name']?></li>
</ul>
</li>
<?php
}elseif($cat['parent_id']==0){
?>
<li><span><?php echo $cat['name'];?></span></li>
<?php
}
?>
<?php }}?>
Output and Problem
The Main category circle in red color is seerah which has two subcategories. showing two times for first one in drop down one subcategory and for second time second subcategory is showing.
DB structure
What i wants:
I wants to show each subcategories under each parent category without repetition , how can i achieve this?
Here is how i handled the problem
<?php
foreach($this->parent_category as $cat){
$html = '';
foreach($this->child_category as $child_cat){
if($cat['id']==$child_cat['parent_id']){
$html .= '<li>' . $child_cat['name'] . '</li>';
// here is all child categories are saved in var.
}
}
if ($html == '') {
?>
<li><span><?php echo $cat['name'];?></span></li>
<?php
} else {
?>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#"><?php echo $cat['name'];?>
<span class="caret"></span></a>
<ul class="dropdown-menu">
<?php echo $html; ?> // here is displayed under parent category
</ul>
</li>
<?php
}
}
?>
Output
To me it seem you did not split your html and loops properly here:
foreach($this->parent_category as $cat){
foreach($this->child_category as $child_cat){
if($cat['id']==$child_cat['parent_id']){
?>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#"><?php echo $cat['name'];?>
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><?php echo $child_cat['name']?></li>
</ul>
</li>
Usually whenever you have a loop you should have some output before any nested loop started. In your case first level loop is about Categories which should become an <li> of parent main menu <ul>.
I think. You need to transform this fragment to:
foreach($this->parent_category as $cat){ ?>
<li ...>
...
<ul ...> <?php
foreach($this->child_category as $child_cat){ ?>
<li>...</li> <?php
} ?>
</ul>
</li> <?php
}
when you do not have repetitive value in $rows, why you use this part again for $cat['name']?
elseif($cat['parent_id']==0){
?>
<li><span><?php echo $cat['name'];?></span></li>
<?php
}
when in first part of foreach you create
<a class="dropdown-toggle" data-toggle="dropdown" href="#"><?php echo $cat['name'];?>

Bootstrap multi-level drop down not working

I am working on a PHP website. And for some reasons, I need to add multiple level dropdown in my navigation bar. I tried the bootstrap class="dropdown-submenu" but I don't know why it has not worked.
<ul class="dropdown-menu">
<?php
$alllinks = mysql_query("SELECT `cid`, `cname` FROM `services` WHERE `parentid`=0");
while($reslink = mysql_fetch_assoc($alllinks)){ ?>
<li class="dropdown-submenu">
<a tabindex="-1" href="<?php echo MYWEBSITE;?>services/<?php echo to_prety_url($reslink['cname']).'-'.$reslink['cid'];?>.html">
<?php echo $reslink['cname'];?>
</a>
<ul class="dropdown-menu">
<li>
<a href="<?php echo MYWEBSITE;?>servicedetail/<?php echo to_prety_url($rowsb['cname']).'-'.$rowsb['cid'];?>.html">
<?php echo $rowsb['cname'];?>
</a>
</li><br>
</ul>
</li><br>
<?php } ?>
</li>
</ul>
Throughout your code You haven't enclosed MYWEBSITE in inverted comma's
you have written.
<?php echo MYWEBSITE;?>
whereas you should write
<?php echo "MYWEBSITE";?>
and You are using the old and Deprecated mysql connector it is higly recommended that you switch to PDO or mysqli.

How to render a Drupal 7 menu structure with divs instead of lists

I want to change the output of the Drupal 7 menu structure which is like:
<?php print render($primary_nav); ?>
outputs:
<ul class="menu nav navbar-nav">
<li class="first expanded">
<a title="" href="lorem">Lorem</a>
<ul class="menu nav">
<li class="first leaf"><a title="" href="/lorem">Lorem</a></li>
<li class="leaf"><a title="" href="/ipsum">Ipsum</a></li>
</ul>
</li>
<li class="leaf"><a title="" href="/dolor">Dolor</a></li>
<li class="expanded"><a title="" href="/sit">Sit</a>
<ul class="menu nav">
<li class="first leaf"><a title="" href="/sit">Amet</a></li>
<li class="leaf"><a title="" href="/consectetur">Consectetur</a></li>
</ul>
</li>
</ul>
how could I have instead of the ul and li the menu rendered with divs.
Thanks
I feel curious... why do you want to do so?
I guess you should try to make a modified copy of 'render' function and call it instead.
EDIT
The print "function" in PHP just outputs the argument received. I guess you should define your own php function, namely print_menu_as_div:
function print_menu_as_div($primary_nav) {
$htmlCode = '<div class="myOwnMenuClass">';
...
/*Generate your HTML code here to display your
menu items and append to $htmlCode*/
...
$htmlCode .= '</div>';
return $htmlCode;
}
Then instad of:
<?php print render($primary_nav); ?>
write:
<?php print print_menu_as_div($primary_nav); ?>
Hope it helps ;)

Show a hierarchy in PHP

I have a database which stores a hierarchy of foods.
Category(id_cat,name_cat);
his_low_cat(id_cat,id_low_cat);
A category can have 0..n low category. If it had no lower category I do a id_cat,-1 field in his_low_cat.
I do not know if it's possible but I would like to show it in a kind of "pulldown menu"
(if you have any other idea on how to show a full hierarchy please suggest it)
Like this :
echo " <div id=\"menu\">
<ul class=\"niveau1\">
<li class=\"sousmenu\">Food
<ul class=\"niveau2\">
<li class=\"sousmenu\">Sous menu 1.1
<ul class=\"niveau3\">
<li>Sous sous menu 1.1.1</li>
</ul>
</li>
<li>Sous menu 1.2</li>
</ul>
</li>
</ul>
</div>";
My first cat is "food" and then it derives into 4 lowers categories, which derive themselves in more.
The problem is that it must be dynamic and load field from my database.
The goal would be to be able to catch the clicked value and use it in another .php
How would I do this?
Recursion is definitely the way to go with this problem, I've coded up this solution:
<?php
function nestElements($elements, $depth=0)
{
foreach($elements as $elementName=>$element)
{
echo str_repeat("\t", $depth).'<ul class="niveau'.($depth+1).'">'."\n";
if(is_array($element))
{
echo str_repeat("\t", $depth+1)."<li class=\"sousmenu\">${elementName}\n";
nestElements($element, $depth+2);
echo str_repeat("\t", $depth+1)."</li>\n";
}
else
{
echo str_repeat("\t", $depth+1)."<li class=\"sousmenu\">${elementName}</li>\n";
}
echo str_repeat("\t", $depth)."</ul>\n";
}
}
nestElements(array("Food"=>array("Meat"=>array("Poultry"=>array("Chicken"=>"Meat/Poultry/Chicken"), "Beef"=>array("Hamburgers"=>"Meat/Beef/Hamburgers", "Steak"=>"Meat/Beef/Steak")), "Dairy"=>array("Cow"=>"Dairy/Cow", "Sheep"=>"Dairy/Sheep")), "name"=>"url"));
?>
Testing with this:
<?php
nestElements(array("Food"=>array("Meat"=>array("Poultry"=>array("Chicken"=>"Meat/Poultry/Chicken"), "Beef"=>array("Hamburgers"=>"Meat/Beef/Hamburgers", "Steak"=>"Meat/Beef/Steak")), "Dairy"=>array("Cow"=>"Dairy/Cow", "Sheep"=>"Dairy/Sheep")), "name"=>"url"));
?>
Results in:
<ul class="niveau1">
<li class="sousmenu">Food</li>
<ul class="niveau2">
<li class="sousmenu">Meat</li>
<ul class="niveau3">
<li class="sousmenu">Poultry</li>
<ul class="niveau4">
<li class="sousmenu">Chicken</li>
</ul>
</ul>
<ul class="niveau3">
<li class="sousmenu">Beef</li>
<ul class="niveau4">
<li class="sousmenu">Hamburgers</li>
</ul>
<ul class="niveau4">
<li class="sousmenu">Steak</li>
</ul>
</ul>
</ul>
<ul class="niveau2">
<li class="sousmenu">Dairy</li>
<ul class="niveau3">
<li class="sousmenu">Cow</li>
</ul>
<ul class="niveau3">
<li class="sousmenu">Sheep</li>
</ul>
</ul>
</ul>
<ul class="niveau1">
<li class="sousmenu">name</li>
</ul>
To parse it you'd have to make a mod_rewrite which redirects to index.php?r=TheURL and from their, explode the r parameter using "/" as the delimeter, then you have a list of menus and submenus that the clicked link was from. By adding another parameter the url coul be automatically generated.
Edit: Fixed problem with original code output seen below
<li class="sousmenu">Sheep</li>
<li class="sousmenu">Sheep</li>
To generate the array:
<?php
function genArray(&$targetArray, $parentID=null){
$res=(is_null($parentID))?mysql_query("SELECT * FROM categorie WHERE id_cat NOT IN (SELECT id_low_cat FROM hislowcat) ORDER BY id_cat DESC;"):mysql_query("SELECT *, (SELECT name_cat FROM categorie WHERE id_cat= '".$parentID ."') AS name_cat FROM hislowcat WHERE id_cat= '" .$parentID ."'");
if(!is_null($parentID) && !mysql_num_rows($res))
{
$res3=mysql_query("SELECT name_cat FROM categorie WHERE id_cat='${parentID}';");
$row3=mysql_fetch_array($res3);
$targetArray[$row3['name_cat']]=$row3['name_cat'];
return;
}
while(($row=mysql_fetch_array($res)))
{
//echo $row->name_cat;
if(is_null($parentID))
{
if(!isset($targetArray[$row['name_cat']]))
{
$targetArray[$row['name_cat']]=array();
}
genArray($targetArray[$row['name_cat']], $row['id_cat']);
}
else
{
genArray($targetArray[$row['name_cat']], $row['id_low_cat']);
}
}
}
$array=array();
genArray($array);
print_r($array);
?>
Notice how $targetArray is set up as a reference, this way we can treat it one-dimensionally.

Categories