Nested dropdown - php

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.

Related

How to Echo Datas From Mysql Properly

I have a mini game which is written in PHP. I want to build a highscore section for it. But I can't echo datas properly. My database
+--------+----------+----------------------------------+---------------------+------+------+
| UserID | Username | Password | EmailAddress | win | lost |
+--------+----------+----------------------------------+---------------------+------+------+
| 1 | utku | e10adc3949ba59abbe56e057f20f883e | utku#utku.com | 3 | 6 |
| 2 | utku2 | e10adc3949ba59abbe56e057f20f883e | utku#sda.com | 5 | 15 |
| 3 | utku3 | e10adc3949ba59abbe56e057f20f883e | sad | 0 | 0 |
+--------+----------+----------------------------------+---------------------+------+------+
I'm trying to echo them with this code (I found it in another question's topic)
<?php include "base.php"; ?>
<?
$query="SELECT Username,win,lost FROM users ORDER BY win";
$results = mysql_query($query);
while ($row = mysql_fetch_array($results)) {
echo '<tr>';
foreach($row as $field) {
echo '<td>' . htmlspecialchars($field) . '</td>';
}
echo '</tr><br>';
}
?>
It prints datas like this
utku3utku30000
utkuutku3366
utku2utku2551515
But I want to print them in this form
Username Win Lost
utku2 5 15
utku 3 6
utku3 0 0
How can I do it. I'm new on PHP
You should not use mysql_ as it is outdated and will be removed in future versions of php.
You should switch to mysqli_ or PDO. (Overview of the MySQL PHP drivers > Choosing an API)
Your problem is:
array mysql_fetch_array ( resource $result [, int $result_type = MYSQL_BOTH ] )
MYSQL_BOTH: [...]By using MYSQL_BOTH (default), you'll get an array with both associative and number indices.[...]
That's why you get each column twice.
A quick fix would be using MYSQL_NUM or MYSQL_ASSOC:
mysql_fetch_array($results, MYSQL_ASSOC)
You should not print tr, td without table tag. Also you did not added th. Can try this
echo '<table><tr><th>User Name</th><th>Win</th><th>Lost</th></tr>';
while ($row = mysql_fetch_array($results)) {
echo '<tr><td>'.$row['Username'].'</td><td>'.$row['win'].'</td><td>'.$row['lost'].'</td></tr>';
}
echo '</table>';
You don't need the foreach loop because the while loop is doing the recursive iteraction, that's why you have twice results:
while ($row = mysql_fetch_array($results)) {
echo '<tr>';
echo '<td>' . htmlspecialchars($field['Username']) . '</td>';
echo '<td>' . htmlspecialchars($field['win']) . '</td>';
echo '<td>' . htmlspecialchars($field['lost']) . '</td>';
echo '</tr><br>';
}

PHP MySQL: Display all column names from a given table and the values for any single given row

I am trying to parse all the column fields and data of a single row of any selected mysql table.
The reason behind this is to make a 'universal'-like Table parser of any given single row.
For example I have this table 'tbl1':
+----+---------------------+---------+---------+--+
| id | date | amounta | amountb | |
+----+---------------------+---------+---------+--+
| 1 | 2014-02-28 05:58:41 | 148 | 220 | |
+----+---------------------+---------+---------+--+
| 2 | 2014-01-20 05:58:41 | 50 | 285 | |
+----+---------------------+---------+---------+--+
| 3 | 2014-03-30 05:58:41 | 501 | 582 | |
+----+---------------------+---------+---------+--+
and I want to be able to select table tbl1 and id = 1 to export into:
<label>id <input type="text" value="1"/></label>
<label>date <input type="text" value="2014-02-28 05:58:41"/></label>
<label>amounta <input type="text" value="148"/></label>
<label>amountb <input type="text" value="220"/></label>
This is what I have thus far:
if ($_GET['p'] && $_GET['table']) {
include ("con.php");
$query = "SELECT * FROM `" . $_GET['table'] . "` WHERE id = '" . $_GET['p'] . "'";
$result = mysql_query($query);
while ($row = mysql_fetch_array($result)) {
$fields[] = $row['0'];
$p = $row;
}
$fields = array();
$res = mysql_query("SHOW COLUMNS FROM `" . $_GET['table'] . "`");
while ($x = mysql_fetch_assoc($res)) {
$fields[] = $x['Field'];
}
foreach($fields as $f) {
foreach($p as $obj) {
echo '<label>' . $f . ' <input type="text" value="' . $p[$f] . '"></label>';
};
}
mysql_close();
}
The problem I'm sure is somewhere between the foreach looping. I know its totally wrong but im not quite sure how to solve this problem.
Basically the idea is to select all column names from $_GET['table'] and for each column name find its value where id = $_GET['p'];
if $p is a single-level array like
Array (
'field1' => 'value1',
'field2' => 'value2',
...
)
and $fields is an array like this
Array (
0 => 'field1',
1 => 'field2',
...
)
Then this should work
foreach($fields as $f) {
echo '<label>' . $f . ' <input type="text" value="' . $p[$f] . '"></label>';
}
Use mysql_fetch_field.
$fields = array();
while($f = mysql_fetch_field($query)) $fields[] = $f->name;
In this way you can get all field names, works for any kind of query rather than just SELECT *

MYSQL PHP Output sorting, get values inbetween output

I have a small problem with MySQL tables pushed into a HTML table.
Here is my SELECT on the database:
$result = mysql_query("
SELECT dat_eb_registrants.id, dat_eb_registrants.first_name, dat_eb_registrants.last_name, dat_eb_registrants.email, dat_eb_registrants.comment, dat_eb_registrants.amount, dat_eb_registrants.published, dat_eb_registrants.transaction_id, dat_eb_registrants.register_date, GROUP_CONCAT(dat_eb_field_values.field_value SEPARATOR '</td><td>')
FROM dat_eb_registrants LEFT JOIN dat_eb_field_values ON dat_eb_registrants.id=dat_eb_field_values.registrant_id
WHERE `event_id` >= 20 AND `event_id` <= 25
GROUP BY dat_eb_registrants.id
ORDER BY $sort $ascdsc
");
Which is pushed into my HTML table using this:
while ($row = mysql_fetch_row($result)) {
echo "<tr>";
echo "<td>" . $row[9] . "</td>";
echo "<td>";
Now, my problem is the fact that this fills my table with a few rows from dat_eb_field_values.field_value, and I can't get other rows ($row[0] to $row[8]) in-between these results.
For example if my $values come from dat_eb_field_values.field_value and my $data comes from dat_eb_registants. This would be my table:
| header 1 | header 2 | header 3 | header 4 | header 5 | header 6 |
-------------------------------------------------------------------
| $value1 | $value2 | $data3 | $value4 | $data1 | $data2 |
| $value1 | $value2 | $data3 | $value4 | $data1 | $data2 |
| $value1 | $value2 | $data3 | $value4 | $data1 | $data2 |
Thanks in advance! Laurent
while ($row = mysql_fetch_row($result)) {
echo "<tr>";
foreach($row AS $val)
echo "<td>" . $val . "</td>";
echo "<td>";
}
that should do
Instead of echoing out the data of $row[9] place it in a array, then spit it out when you feel it's necessary (and after you've checked for the other elements)
For example change this:
while ($row = mysql_fetch_row($result)) {
echo "<tr>";
echo "<td>" . $row[9] . "</td>";
echo "<td>";
To this:
while ($row = mysql_fetch_row($result)) {
$myArray[] ="<tr><td>" . $row[9] . "</td>""<td>";
instead of mysql_fetch_row use mysql_fetch_array
and
ORDER BY $sort $ascdsc change it to
ORDER BY '".$sort."', '".$ascdsc."'
exemple :
by using mysql_fetch_array try echo this
echo $row['dat_eb_registrants.id'] ;
your sql is hard to read
use this
SELECT dr.id, dr.first_name, dr.last_name, dr.email, dr.comment, dr.amount, dr.published, dr.transaction_id, dr.register_date, GROUP_CONCAT(df.field_value SEPARATOR '</td><td>')
FROM dat_eb_registrants dr
LEFT JOIN dat_eb_field_values df
ON dr.id=df.registrant_id
WHERE `event_id` >= 20 AND `event_id` <= 25
GROUP BY dr.id
ORDER BY '".$sort."', '".$ascdsc."'
but you have accepted the answer here !!

Tree issue in 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

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/>";

Categories