Tree issue in PHP - php

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

Related

How to display the comment only once but display all images from mysql in PHP?

I want to display the comment only once e.g (testsetest) with the related images (which has the same imagesid by connecting the two tables).
Example (that I want to achieve):
comment: fool with images: name1, name 2
Caption of the wrong output.
The database structure
posts:
| commentid | comment | iamgesid |
------------------------------------
| 1 | fool | 5557 |
| 2 | fool2 | 5585 |
------------------------------------
multiple_image:
| id | image | imagesid |
---------------------------
| 1 | name1 | 5557 |
| 2 | name2 | 5557 |
| 3 | name3 | 5585 |
---------------------------
This is my current code:
$sql = "SELECT image, posts.imagesid, multiple_image.imagesid, comment
FROM multiple_image JOIN posts ON (multiple_image.imagesid=posts.imagesid)";
$result = $conn->query($sql);
if (!$result) {
trigger_error('Invalid query: ' . $conn->error);
}
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo $row['comment'];
$imgs= "<div id='img_div'><img width='' src='upload/".$row['image']."' ></div>";
echo $imgs;
}
}
You will need to control break the result and order by the commentid
Please see the updated code.
$sql = "SELECT
image,
posts.imagesid,
multiple_image.imagesid,
comment
FROM
multiple_image
JOIN posts ON (multiple_image.imagesid=posts.imagesid)
ORDER BY
commentid
";
$result = $conn->query($sql);
if (!$result) {
trigger_error('Invalid query: ' . $conn->error);
}
if ($result->num_rows > 0) {
// output data of each row
$comment = '';
while($row = $result->fetch_assoc()) {
if($comment != $row['comment']){
echo $row['comment'];
$comment = $row['comment'];
}
$imgs= "<div id='img_div'><img width='' src='upload/".$row['image']."' ></div>";
echo $imgs;
}
}
You can create a flag and check if it is 0. If it is 0 then you can show comment else you dont need to show comment. Check below code:
if ($result->num_rows > 0) {
// output data of each row
$loop = 0;
while ($row = $result->fetch_assoc()) {
if ($loop == 0) {
echo $row['comment'];
}
$imgs = "<div id='img_div'><img width='' src='upload/" . $row['image'] . "' ></div>";
echo $imgs;
$loop++;
}
}
Hope it helps you.
I hope it will help out:
$sql = "SELECT
image,
posts.imagesid,
multiple_image.imagesid,
comment
FROM
multiple_image
JOIN posts ON (multiple_image.imagesid=posts.imagesid)
ORDER BY
commentid";
$result = $conn->query($sql);
if (!$result) {
trigger_error('Invalid query: ' . $conn->error);
}
if ($result->num_rows > 0) {
$comment = array();
while ($row = $result->fetch_assoc()) {
// check imagesid is not exist in array
if (in_array($row['imagesid'], $comment) == false) {
echo $row['comment'];
$comment[] = $row['imagesid'];
}
$imgs = "<div id='img_div'><img width='' src='upload/" . $row['image'] . "' ></div>";
echo $imgs;
}
}

Optimizing / Simplify Query of Multi-Layer Category

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;
}

Grouping a query with php

Basic question!
I have 2 tables
PRODUCE
+-----+--------------+
| id | fruit_name |
+--------------------+
| 1 | Apple |
| 2 | Banana |
| 3 | Carrot |
+-----+--------------+
VARIETIES
+-----+---------------+----------------+
| id | fk_fruit_id | variety_name |
+-----+---------------+----------------+
| 1 | 1 | Cox |
| 2 | 1 | Braeburn |
| 3 | 2 | Chester |
| 4 | 3 | Kotaka |
| 5 | 3 | Imperial |
| 6 | 3 | Oneal |
+-----+---------------+----------------+
I'd like to output a list of varieties per fruit e.g.
APPLE - Cox, Braeburn
BANANA - Chester
CARROT - Kotaka, Imperial, Oneal
My current code is
$query = "SELECT * FROM produce, varieties WHERE produce.id = varieties.fk_fruit_id";
$result = mysql_query($query) or die('Error : ' . mysql_error());
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$produce_fruit_code = $row['fruit_code'];
$variety_name = $row['variety_name'];
echo $produce_fruit_code.' - '.$variety_name.'<br/>';
}
which outputs:
Apple - Cox
Apple - Braeburn
Banana - Chester
Carrot - Kotaka
Carrot - Imperial
Carrot - Oneal
Not a million miles away, but still not there. Any help is much appreciated, thanks!
You probably could get one chunky sql statement to do that for you but I'd opt for data juggling with arrays.
For example (not tested and excuse the formatting):
$query = "SELECT * FROM produce, varieties WHERE produce.id = varieties.fk_fruit_id";
$result = mysql_query($query) or die('Error : ' . mysql_error());
$res=array();
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$produce_fruit_code = $row['fruit_code'];
$variety_name = $row['variety_name'];
if(isset($res[$produce_fruit_code])){
$res[$produce_fruit_code]+=','.$variety_name;
}else{
$res[$produce_fruit_code]=$variety_name;
}
}
print_r($res);
If you are using MySQL you can use the group_concat extension on grouping. Something along the lines of:
SELECT
f.fruitname as fruit,
GROUP_CONCAT(distinct v.varietyname separator ',') as variety
FROM fruit f JOIN varieties v ON produce.id = varieties.fk_fruit_id;
or similar. Sorry my sql is a little rusty quite now.
For more look at this article
http://www.mysqlperformanceblog.com/2006/09/04/group_concat-useful-group-by-extension/
and of course here:
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html
If you dont work with MySQL and your database doesn't support group_concat think about buffering those results. In large databases and with many simultaneous users your application can considerably slow down when having to download all data and store it in locally every time.
This won't get you all the way, but it will get you most of what you want. There are some edge cases that are problematic.
$query = "SELECT * FROM produce, varieties WHERE produce.id = varieties.fk_fruit_id";
$result = mysql_query($query) or die('Error : ' . mysql_error());
$produce_fruit_code = "";
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
if ($produce_fruit_code != $row['fruit_code'])
{
$produce_fruit_code = $row['fruit_code'];
echo "<br/>".$produce_fruit_code." - ". $row['variety_name'];
} else {
echo ", ".$row['variety_name'];
}
}
$query = "SELECT * FROM produce, varieties WHERE produce.id = varieties.fk_fruit_id";
echo "<dl>";
$result = mysql_query($query) or die('Error : ' . mysql_error());
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
if($row['fruit_name'] != $current_fruit_name) {
$current_fruit_name = $row['fruit_name'];
echo "<dt>$current_fruit_name</dt>";
}
echo "<dd>" . $row['variety_name'] . "</dd>";
}
    echo "";
If you want some CSS that will make a definition list look like the Name - X,Y,Z like in the question, let me know.
You can query this directly
SELECT
f.fruitname as fruit,
GROUP_CONCAT(distinct v.varietyname separator ',') as variety
FROM fruit f JOIN varieties v ON produce.id = varieties.fk_fruit_id;
GROUP BY produce.id
Sort everything into arrays in your while loop. This should work:
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$produce_fruit_code = $row['fruit_code'];
$variety_name = $row['variety_name'];
if ($produce_fruit_code == "Apple") {
$apple_array[] = $variety_name;
}
if ($produce_fruit_code == "Banana") {
$banana_array[] = $variety_name;
}
if ($produce_fruit_code == "Carrot") {
$carrot_array[] = $variety_name;
}
}
echo "Apples:" . implode(", ", $apple_array) . "<br/>";
echo "Bananas:" . implode(", ", $bananas_array) . "<br/>";
echo "Carrots:" . implode(", ", $carrots_array) . "<br/>";

sub category by php and mysql table

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 :)

Nested dropdown

I'm building a form with php/mysql. I've got a table with a list of locations and sublocations. Each sublocation has a parent location. A column "parentid" references another locationid in the same table. I now want to load these values into a dropdown in the following manner:
--Location 1
----Sublocation 1
----Sublocation 2
----Sublocation 3
--Location 2
----Sublocation 4
----Sublocation 5
etc. etc.
Did anyone get an elegant solution for doing this?
NOTE: This is only psuedo-code.. I didn't try running it, though you should be able to adjust the concepts to what you need.
$parentsql = "SELECT parentid, parentname FROM table";
$result = mysql_query($parentsql);
print "<select>";
while($row = mysql_fetch_assoc($result)){
$childsql = "SELECT childID, childName from table where parentid=".$row["parentID"];
$result2 = mysql_query($childsql);
print "<optgroup label=\".$row["parentname"]."\">";
while($row2 = mysql_fetch_assoc($result)){
print "<option value=\"".$row["childID"]."\">".$row["childName"]."</option>\n";
}
print "</optgroup>";
}
print "</select>";
With BaileyP's valid criticism in mind, here's how to do it WITHOUT the overhead of calling multiple queries in every loop:
$sql = "SELECT childId, childName, parentId, parentName FROM child LEFT JOIN parent ON child.parentId = parent.parentId ORDER BY parentID, childName";
$result = mysql_query($sql);
$currentParent = "";
print "<select>";
while($row = mysql_fetch_assoc($result)){
if($currentParent != $row["parentID"]){
if($currentParent != ""){
print "</optgroup>";
}
print "<optgroup label=\".$row["parentName"]."\">";
$currentParent = $row["parentName"];
}
print "<option value=\"".$row["childID"]."\">".$row["childName"]."</option>\n";
}
print "</optgroup>"
print "</select>";
Are you looking for something like the OPTGROUP tag?
optgroup is definitely the way to go. It's actually what it's for,
For example usage, view source of http://www.grandhall.eu/tips/submit/ - the selector under "Grandhall Grill Used".
You can use and space/dash indentation in the actual HTML. You'll need a recusrive loop to build it though. Something like:
<?php
$data = array(
'Location 1' => array(
'Sublocation1',
'Sublocation2',
'Sublocation3' => array(
'SubSublocation1',
),
'Location2'
);
$output = '<select name="location">' . PHP_EOL;
function build_items($input, $output)
{
if(is_array($input))
{
$output .= '<optgroup>' . $key . '</optgroup>' . PHP_EOL;
foreach($input as $key => $value)
{
$output = build_items($value, $output);
}
}
else
{
$output .= '<option>' . $value . '</option>' . PHP_EOL;
}
return $output;
}
$output = build_items($data, $output);
$output .= '</select>' . PHP_EOL;
?>
Or something similar ;)
Ideally, you'd select all this data in the proper order right out of the database, then just loop over that for output. Here's my take on what you're asking for
<?php
/*
Assuming data that looks like this
locations
+----+-----------+-------+
| id | parent_id | descr |
+----+-----------+-------+
| 1 | null | Foo |
| 2 | null | Bar |
| 3 | 1 | Doe |
| 4 | 2 | Rae |
| 5 | 1 | Mi |
| 6 | 2 | Fa |
+----+-----------+-------+
*/
$result = mysql_query( "SELECT id, parent_id, descr FROM locations order by coalesce(id, parent_id), descr" );
echo "<select>";
while ( $row = mysql_fetch_object( $result ) )
{
$optionName = htmlspecialchars( ( is_null( $row->parent_id ) ) ? "--{$row->descr}" : "----{$row->desc}r", ENT_COMPAT, 'UTF-8' );
echo "<option value=\"{$row->id}\">$optionName</option>";
}
echo "</select>";
If you don't like the use of the coalesce() function, you can add a "display_order" column to this table that you can manually set, and then use for the ORDER BY.

Categories