I have a MySQL table ( name: item_categories ) having the following schema:
id INT(11) PRIMARY KEY, AUTO INCREMENT
category_name VARCHAR(100) NOT NULL
parent_id INT(11) NOT NULL, Default 0
Sample Data:
id category_name parent_id
=============================
1 Fruit 0
2 Animal 0
3 Furniture 0
4 Apple 1
5 Orange 1
6 Cat 2
7 Dog 2
8 Black Dog 7
9 White Dog 7
If I have to list out the categories with their parent categories, I have to loop through the database table many times.
My question is: How can I simplify the loop task?
Current loop task query:
// 1st query
$sql = "SELECT * FROM item_categories";
$rs = $db->query($sql);
while($row = $db->result($rs)) {
if((int)$row['parent_id'] === 0) {
// it is parent
echo $row['category_name'] . PHP_EOL;
} else {
$category = $row['category_name'];
// it has parent
$sql = "SELECT * FROM item_categories WHERE id=" . $row['parent_id'];
$rs2 = $db->query($sql);
$row2 = $db->result($rs);
$parent_id = (int)$row2['parent_id'];
while($parent_id != 0) {
$sql = "SELECT * FROM item_categories WHERE id=" . $row['parent_id'];
$rs2 = $db->query($sql);
$row2 = $db->result($rs);
$parent_id = (int)$row2['parent_id'];
$category = $row2['category_name'] . ' > ' . $category;
}
echo $category;
}
}
Which will output:
Fruit
Animal
Furniture
Fruit > Apple
Fruit > Orange
Animal > Cat
Animal > Dog
Animal > Dog > Black Dog
Animal > Dog > White Dog
Based on the link i gave you in the comment - try this:
function renderBreadcrumbs($db, $id, $path = null) {
$res = $db->query("SELECT id, parent_id, category_name FROM item_categories WHERE id = " . $id);
$row = $db->result($res);
$path = $row['category_name'] . ' > ' . $path;
if($row['parent_id'])
$path = renderBreadcrumbs($db, $row['parent_id'], $path);
return $path;
}
$res = $db->query("SELECT id, parent_id, category_name FROM item_categories ORDER BY parent_id ASC");
while($row = $db->result($res)) {
$breadcrumb = null;
if(!$row['parent_id'])
$breadcrumb .= $row['category_name'];
else
$breadcrumb .= renderBreadcrumbs($db, $row['parent_id'], $row['category_name']);
echo $breadcrumb . PHP_EOL;
}
Related
I have this mysql table "categories":
id category parent
1 category1 NULL
2 subcategory1 1
3 category2 NULL
4 subcategory2 2
and I want to get this result:
category1
subcategory1
subcategory2
category2
to get this result I use this code, but is very slow:
foreach($db->query("SELECT * FROM categories WHERE parent IS NULL") as $parent)
{
$t=0;
categories($db,$t,$parent['id'],$parent['category']);
}
function categories($db,$t,$id,$category)
{
echo"<option value=".$id.">";//
for($i=0;$i<$t;$i++) {echo" "; $GLOBALS['cat'].=" ";}
echo $category."</option>";//" ".$id.
$GLOBALS['cat'].=$category."<br>";
$t++;
if($db->query("SELECT * FROM categories WHERE parent=".$id)->rowCount()>0)
{
foreach($db->query("SELECT * FROM categories WHERE parent=".$id) as $child)
categories($db,$t,$child['id'],$child['category']);
}
}
Do you have a faster solution?
Thanks
If you know the depth of your tree (maximum or desired), you can have it all in SQL, flattened to a row representing path:
SELECT c.category, c1.category AS sub1, c2.category AS sub2, c3.category AS sub3
FROM categories c
LEFT JOIN
(categories c1
LEFT JOIN
(categories c2
LEFT JOIN categories c3
ON c3.parent = c2.category)
ON c2.parent = c1.category)
ON c1.parent = c.category
WHERE c.parent IS NULL;
Having that, it's not a big deal to present it in UI accordingly.
$sql = "SELECT id, name, parent_id,
(SELECT COUNT(*) FROM categories WHERE parent_id = cat.id) as child_count
FROM categories cat";
$result = db_select_all($sql);
function build_menu($pid, $level = 1) {
global $result;
$filtered = array_filter($result, function($elem) use($pid) {
return $elem['parent_id'] == $pid;
});
if(empty($filtered)) return;
foreach($filtered as $item) {
extract($item);
echo "<div>" . str_repeat("---", $level) . $name;
build_menu($id, $level + 1);
echo "</div>" . PHP_EOL;
}
}
$menu_elements = array_filter($result, function($item) {
return $item['parent_id'] == '';
});
foreach($menu_elements as $menu) {
$name = $menu['name'];
$id = $menu['id'];
echo "<div>" . $name;
build_menu($id);
echo "</div>" . PHP_EOL;
}
I am working in php and mysql, I have a table category, I need to display subcategoies under parent categories. Like
cat1
-> Subcat1
-> Subcat11
-> Subcat2
--> Subcat21
--> Subcat211
cat2
-> Subcat2
-> Subcat21
-->Subcat22
-> Subcat3
--> Subcat31
--> Subcat311
My Table structure is like :
CREATE TABLE IF NOT EXISTS `category` (
`cat_id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'This is primary key of the table',
`name` varchar(255) DEFAULT NULL,
`parent_cat_id` bigint(11) NOT NULL,
PRIMARY KEY (`cat_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
can you please help me out, how can execute my query.
example:
<?php
class RightMenu {
public $menu;
public $patch = '';
public function getMenu($parent = 0) {
$DB = new DataBase();
$result = $DB->exec("SELECT * FROM cont_sections WHERE parentid = $parent AND status = 1 ORDER BY name;");
if(mysql_num_rows($result) > 0) {
echo '<ul>';
while($row = mysql_fetch_assoc($result)) {
if($row['parentid'] == 0){
$this->patch = '';
}
$this->patch .= '/' . $row["translit"];
echo '<li>' . $row["name"] . '';
echo $this->getMenu($row["id"]);
echo '</li>';
}
echo '</ul>';
}
mysql_free_result($result);
unset($DB);
}
}
?>
use SELF JOIN
SELECT p.cat_id, p.name, c.cat_id, c.name
FROM tbl_category p
INNER JOIN tbl_category c ON p.cat_id = c.parent_cat_id
Then manipulate the resultant array with PHP to display in tabular form
You need to write a recursive function to display Category & sub-cat
getAllSubCats(0);
function getAllSubCats($cat, $depth = NULL)
{
$this_cat = mysql_fetch_object(mysql_query("select * from categories where id= '$cat'"));
$indent = str_repeat(" ", $depth);
echo $indent . $this_cat->name . "<br />";
$result = mysql_query("select * from categories where parent_cat_id = '$cat'");
while($cat = mysql_fetch_object($result))
{
getAllSubCats($cat->id, $depth + 1);
}
}
Or use following query If it is one 2 one relation
SELECT cat_id, name, (SELECT name FROM categories WHERE cat_id = a.parent_id) parent_name FROM categories a
i have a table General whose structure like this
----------------------------------
id | name | parent_id
------------------------------------
1 | root_category | Null
2 | Appare | 1
3 | Accessories | 1
4 | Shirt | 2
5 | Pants | 2
6 | hand Bags | 3
7 | jewelry | 3
And i store the value of general table using from in my product table
product table which contain all the information about product
in product table
p_id | 1
p_name | bla
p_weight | 250
g_id | 5
g_name | pants
g_parent | 2
i Want to generate complete tree using
->g_id -> g_name -> g_parent
tree should look like this
Root Category
- Apparel
-- Shirts
-- Pants
- Accessories
-- Handbags
-- Jewelry
i have tried recursive function but its not working which is
function get_categories($parent = $g_parent)
{
$html = '<ul>';
$query = mysql_query("SELECT * FROM `general` WHERE `parent_id` = '$parent'");
while($row = mysql_fetch_assoc($query))
{
$current_id = $row['id'];
$html .= '<li>' . $row['name'];
$has_sub = NULL;
$has_sub = mysql_num_rows(mysql_query("SELECT COUNT(`parent_id`) FROM `general` WHERE `parent_id` = '$current_id'"));
if($has_sub)
{
$html .= get_categories($current_id);
}
$html .= '</li>';
}
$html .= '</ul>';
return $html;
}
print get_categories();
but its not working.... :(
You should try this... its working code.. also see the output screenshot (output screen)
<?php
function get_categories(){
$con = mysql_connect("localhost","root","");
if (!$con){
die('Could not connect: ' . mysql_error());
}
mysql_select_db("stackoverflow", $con);
$result = mysql_query("SELECT g.`name` AS `category`, GROUP_CONCAT(gj.`name`) AS `name`
FROM `general` g INNER JOIN `general` gj ON g.`id` = gj.`parent_id` GROUP BY g.`id` ");
$i=0;
while($row = mysql_fetch_array($result)){
$data[$i]['category'] = $row['category'];
$data[$i]['name'] = $row['name'];
$i++;
}
$html = $data[0]['category']."<br>";
unset($data[0]);
foreach($data as $key => $listing){
$html .= " - ".$listing['category']."<br>";
$exp = explode(",",$listing['name']);
$count_exp = count($exp);
for($j=0; $j<=$count_exp-1;$j++){
$html .= " -- ".$exp[$j]."<br>";
}
}
return $html;
}
print_r(get_categories());
?>
Output Screen
Change this
print get_categories();
To
print get_categories(1);
an empty string is not going to match a NULL value in MySQL, hence you need to supply your starting id. Unless you wanna modify your function to do the extra checking if $parent is null.
try this with some changing :
function get_categories($parent)
{
$html = '<ul>';
$query = mysql_query("SELECT * FROM `general` WHERE `parent_id` = '$parent'");
while($row = mysql_fetch_assoc($query))
{
$current_id = $row['id'];
$html .= '<li>' . $row['name'];
$has_sub = NULL;
$has_sub = mysql_num_rows(mysql_query("SELECT COUNT(`parent_id`) as count FROM `general` WHERE `parent_id` = '$current_id'")); // change here
if($has_sub['count'] > 0) // change here
{
$html .= get_categories($current_id);
}
$html .= '</li>';
}
$html .= '</ul>';
return $html;
}
print get_categories(1); // change here
this is my code, it displays all the categories like
A
-A.1
-A.2
B
-B.1
-B.2
And now i want it displays only
A.1
A.2
B.1
B.2
Any idea?
function current_categories($m,$id){
$cat_array=array();
$sql = "select * from `category`";
$query = DB::Query($sql);
while($row = DB::fetch_array($query)){
$cat_array[] = array($row['id'],$row['name'],$row['classid'],$row['sort']);
}
if($id==""){
$id=0;
}
$n = str_pad('',$m,'-',STR_PAD_LEFT);
$n = str_replace("-"," ",$n);
for($i=0;$i<count($cat_array);$i++){
if($cat_array[$i][2]==$id){
echo "<li>"."".$cat_array[$i][1]."</li>";
current_categories($m+2,$cat_array[$i][0]);
}
}
}
I don't know what value you put in as classid for the toplevel classid values. NULL or -1 perhaps?
function second_level_categories(){
$sql = " SELECT lvl2.* FROM `category` as lvl1 "
." JOIN `category` as lvl2"
." ON lvl1.id = lvl2.parent_id"
." WHERE lvl1.parent_id=VALUE_FOR_TOP_LEVEL"
." ORDER BY lvl1.sort ASC, lvl2.sort ASC"
$result = DB::Query($sql);
while($category = DB::fetch_array($result)){
echo '<li><a href="/team/index.php?gid='.$category['id'].'">"';
echo $category['name'];
echo '</a></li>';
}
}
I have a table name category with following cols
cat_id | name | parent
1 | item 1 | 0
2 | item 2 | 1
3 | item 3 | 0
4 | item 4 | 1
5 | item 5 | 3
How i can display it in a menu like this
Item 1
> Item 2
> Item 4
Item 3
> Item 5
Please help
Here is the function that can be used:
// $current_cat_id: the current category id number
// $count: just a counter, call it as 0 in your function call and forget about it
// Gets the drop down list recurssively of categories //
function find_pages_recursive($current_cat_id, $count)
{
global $db; // the database object instance
static $option_results;
// if there is no current category id set, start off at the top level (zero)
if (!isset($current_cat_id))
{
$current_cat_id = 0;
}
$count++;
// query the database for the sub-categories of whatever the parent category is
$query = 'SELECT id, title from pages where parid = ' . $current_cat_id . ' order by id';
$get_options = $db->execute($query);
$num_options = $db->count_select();
// our category is apparently valid, so go ahead :P
if ($num_options > 0)
{
while (list($cat_id, $cat_name) = mysql_fetch_row($get_options))
{
// if its not a top-level category, indent it to show that its a child category
if ($current_cat_id != 0)
{
$indent_flag = '';
for ($x = 2; $x <= $count; $x++)
{
$indent_flag .= '----';
}
$indent_flag .= ' ';
}
$option_results[$cat_id] = $indent_flag . $cat_name;
// now call the function again, to recurse through the child categories
find_pages_recursive($cat_id, $count);
}
}
return $option_results;
}
How To Use It:
echo '<select name="pages" id="pages">' . "\n";
echo '<option value="">--Select Page--</option>' . "\n";
$get_options = find_pages_recursive(0, 0);
if (count($get_options) > 0)
{
foreach ($get_options as $key => $value)
{
$options .= "<option value=\"$key\"";
$options .= ">$value</option>\n";
}
}
echo $options;
echo '</select>' . "\n";
Make sure to connect to the database first :)