I try to get the child id's of products dynamically.Below is my table structure.
parent|child
---------------------
44 | 35,6,47,5,50
---------------------
47 | 8,9
---------------------
50 | 12, 15
am going to pass only one parent id and get the child ids, and if anyone of child ids having again child, then i have to fetch that record also.example 44->35,6,47,5,50 in this 47 and 50 is having child ids, so my final output should be like this 44-> 35,6,47,8,9,5,50,12,15.
I tried below this,
$sql=mysql_fetch_assoc(mysql_query("select * from chain_product where parent='44'"));
$parent=$sql['parent'];
$child=$sql['child'];
$ex=explode(",",$child);
$count=sizeof($ex);
for($i=0;$i<$count;$i++)
{
$list=add_child($ex[$i],$child);
$check=explode(",",$list);
$chck_count=sizeof($check);
if($chck_count>$count)
{
$exit=add_child($ex[$i],$list);
print_r($exit);
}
}
function add_child($main,$ch)
{
$find=mysql_query("select * from chain_product where parent='$main'");
$res=mysql_fetch_assoc($find);
if($res)
{
$replace=$main.",".$res['child'];
$alter=str_replace($main,$replace,$ch);
echo $alter;
}
}
but i get the result like this,
35,6,47,8,9,5,5035,6,47,5,50,12,15
but i need output should be like this..
35,6,47,8,9,5,50,12,15.
can anyone help me to do this..
Your database structure isnt optimal for this, this would be better:
id | parent
1 | 0
2 | 1
3 | 1
4 | 2
5 | 2
This way you can do something recursive:
function getChilds($parent=0, $depth=0){
// Select the items for the given $parent
$query = $conn->mysqli_query("SELECT id WHERE parent=".$parent); // mysqli is better, but mysql will do fine
// get the items by the parent giving as input:
while($fetch = $query->fetch_assoc() ){
echo str_repeat('-', $depth) . " ".$fetch['id'];
getChilds($fetch['id'], $depth+1); // Use id of this line to find its childs
echo "<br />";
}
}
getChilds(0); // And start it. The 0 is optional, I personaly prefer -1. Whatever rows your boat
This is called a tree structure and should give something like this:
1
- 2
- - 4
- - 5
- 3
In this example I use an echo for display purposes, you can return the values via an array, same principle
To answer a bit better, your current structure could support a similar method, but because you use strings, it will be allow slower and alot less flexible. You can see the difference in the code you are using, and the amount I just used. If you would remove the echo's and only return arrays, it will be even smaller :)
Related
I am pulling data out of a table that has these fields:
zipcode,city,state,county
My question is that some zip codes are in multiple cities, and some cities are in multiple zip codes... so is there a way to have all the data put into an array, then group all of the zip codes in order, then build a table out of that, so that it puts them in order, but if the data is redundant, like the zip, city, state and county are already in the array, then it skips it?
so then I can print it to the browser using echo, into a table like this:
74801 | Shawnee, Oklahoma | Pottawatomie
74801 | Bethel, Oklahoma | Pottawatomie
74801 | Johnson, Oklahoma | Pottawatomie
74851 | McLoud, Oklahoma | Pottawatomie
74851 | Dale, Oklahoma | Pottawatomie
etc.
But in the case of these:
74015 | CATOOSA, Oklahoma | Rogers
74015 | COTOOSA, Oklahoma | Rogers
Because those are duplicates in those fields (not in the rest of the table), I need it to skip showing it twice.
I think it is something like this:
$zipArray = array();
$zipCode = $dbhhandle->zip;
$cityName = $dbhhandle->city;
$countyName = $dbhhandle->county;
if($zipArray[$zipCode][$cityName] != $countyName) {
$zipArray[$zipCode][$cityName] = $countyName;
}
but I'm not sure if that is the right way to do it.
Then once I have the array built, how do I build the table?
Your code looks pretty close, but it's missing the state. So change the elements of the array into associative arrays with state and county elements.
Also, you need to check whether there's an entry for the zip code at all, before checking whether it's a duplicate, otherwise you'll access an undefined index.
$zipArray = array();
$zipCode = $dbhhandle->zip;
$cityName = $dbhhandle->city;
$countyName = $dbhhandle->county;
$stateName = $dbhandle->state;
if(!isset($zipArray[$zipCode][$cityName]) || $zipArray[$zipCode][$cityName]['county'] != $countyName) {
$zipArray[$zipCode][$cityName] = array('county' => $countyName, 'state' => $stateName);
}
To display the table, you use nested loops.
foreach ($zipArray as $zip => $cities) {
foreach ($cities as $city => $cityData) {
echo "<tr><td>$zip</td><td>$city, {$cityData['state']}</td><td>{$cityData['county']}</td></tr>";
}
}
I have a table in a MySQL database that represents a genetic language tree. Each row is a language with an ID and a parent ID; for example:
id | language | parent
-----+---------------------+--------
1 | Proto-Indo-European | NULL
6 | Celtic | 1
8 | Insular Celtic | 6
9 | Goidelic | 8
14 | Irish | 9
16 | Manx | 9
21 | British | 8
22 | Welsh | 21
109 | Germanic | 1
115 | West Germanic | 109
117 | Anglo-Saxon | 115
118 | Anglic | 117
119 | Old English | 118
My goal is to turn these rows into a pretty nested HTML list with aggregate counters after each language that has any child languages, using a simple recursive PHP function, resulting in something like this (based on the languages in the example rows above):
Proto-Indo-European (11)
Celtic (6)
Insular Celtic (5)
Goidelic (2)
Irish
Manx
British (1)
Welsh
Germanic (4)
West Germanic (3)
Anglo-Saxon (2)
Anglic (1)
Old English
I have the following PHP function (simplified here), which creates a multidimensional array with the proper structure:
function select_languages_hierarchical($parent = NULL) {
global $db;
$branch = array();
$query = "SELECT * FROM languages WHERE parent = $parent";
if ($q = $db->query($query)) {
while ($row = $q->fetch_assoc()) {
$element['id'] = $row['id'];
$element['name'] = $row['language'];
$children = select_languages_hierarchical($row['id']);
if ($children) {
$element['children'] = $children;
}
$branch[] = $element;
}
}
return $branch;
}
This produces an array that matches the nested list above, with nested arrays being in the children element of each array.
However, I simply cannot for the life of me, despite much brain-racking, Googling, and looking through oodles of recursion, aggregation-counting, and array-counting questions here on SO, figure out a way to create the counters that describe the number of descendent languages for each language.
Whatever I do, wherever I create, modify, and use my counter variables, and whatever I try counting (whether doing a ˋ$count++ˋ every time I iterate over a language, do a ˋcount($children)ˋ, etc.), I always end up with results where the counter is not reset when the function reaches a ‘higher’ level, so that I get lists like this instead:
Proto-Indo-European (12)
Celtic (6)
Insular Celtic (5)
Goidelic (2)
Irish
Manx
British (4)
Welsh
Germanic (9)
West Germanic (12)
Anglo-Saxon (14)
Anglic (15)
Old English
– Or something like that—the numbers and how they add up vary in the various different implementations I’ve attempted; but they all have in common that the counter keeps being increased throughout, without ever being reset. Or alternatively, if I do try to reset it at some point, naturally it gets reset on every iteration, leaving me with:
Proto-Indo-European (2)
Celtic (2)
Insular Celtic (1)
Goidelic (2)
Irish
Manx
British (1)
Welsh
Germanic (1)
West Germanic (1)
Anglo-Saxon (1)
Anglic (1)
Old English
Clearly, logic is not my strong suit here.
Can someone help my brain from spontaneously combusting and/or imploding by suggesting a way for me to achieve the kind of ‘intelligent tallying’ that I’m looking for here?
Thinking about it, instead of running a zillion recursive queries in PHP, you could just do a basic select * and build your tree in PHP, and do the counting there. Of cousre, this'd only be useful if you want the entire language tree.
$lang = array();
$sql = "SELECT * FROM languages";
... run query ...
while($row = fetch results) {
// store this lang's node
$lang[$row['id']]['name'] = $row['name'];
// add this language to its parent's child array
$lang[$row['parent']]['children'][$row['id']] = $row['id'];
// increment its parent's counter
$lang[$row['parent']]['count']++;
}
Now, this will probably spew out a bunch of warnings about undefined arrays and whatnot, since I'm not testing for the existence of a parent before trying to updates it's counts. But that's just some basic if (!isset()) { initialize node } type stuff.
Output into your nested <ul> would be a recursive function, but since you've now got the child-node counts in your tree already, it'll be much simpler:
function output($id = 1) { // assuming "1" is your tree root node
echo '<li>' . $lang[$id]['name'] . '(' . $lang[$id]['count'] . ')';
if ($lang[$id]['count'] > 0) {
echo '<ul>';
foreach($lang[$id]['children'] as $childID) {
output($childID);
}
echo '</ul>';
}
echo '</li>';
}
I have a database connected to my site that is recording actions taken by a user on an application we have built. The application holds a number of images, which the user can view and download, and the application tracks, per user, which image they have viewed delimited by a comma
What I want to do is write a PHP script that will allow me to turn this delimited text string into a calculated table format
If the database has example records of:
1 | 1-A, 1-B, 2-A, 2-C
2 | 1-A
3 | 1-B, 2-C
4 |
5 | 1-A, 1-B, 1-C, 2-A
To which I wanted to write a script that would be able to output this as:
1-A = 3
1-B = 3
1-C = 1
2-A = 2
2-C = 2
(I want to point out, I'm not suggesting that I want to have variables named after each entry, with its calculated total as the value, I'm open to however is best to return this value)
My first step was to explode each record into an array, but then I wasn't sure as to my next step to turn this into something I can write into a table.
I realise the database is very poorly structured, but unfortunately I haven't written it, and so I have no ability to re-structure the data is stored.
Kind regards
this should work:
<?php
$values = array (
'1' => '1-A, 1-B, 2-A, 2-C',
'2' => '1-A',
'3' => '1-B, 2-C',
'4' => '',
'5' => '1-A, 1-B, 1-C, 2-A'
);
$valueCounts = array();
foreach($values as $value)
{
foreach(explode(', ', $value) as $val)
{
if(!key_exists($val, $valueCounts))
{
if($val) $valueCounts[$val] = 1;
}
else
{
$valueCounts[$val]++;
}
}
}
ksort($valueCounts);
foreach($valueCounts as $value => $count)
{
echo "$value = $count<br />";
}
?>
result:
1-A = 3
1-B = 3
1-C = 1
2-A = 2
2-C = 2
if you're not sure how to populate the $values array, please paste the database code and I will try and incorporate it into the above.
Thanks in advance for any help offered.
I'm performing a query that returns something like this:
route | busnumber
2 300
4 123
2 455
12 934
My goal is to print/echo a list of all "busnumber" were "route" = 2.
I know I can do a query on the DB to do this but I don't want to run this query for each and every route. The result set is actually part of one master, complex query so I need to accomplish my goal using the array.
The query works correctly and does display the appropriate info. I also return the results into an array. i.e ...
$query=("SELECT * from foo")
$result=mysql_fetch_assoc($query);
My current code looks like this (note my comments):
mysql_data_seek( $result,0); // because I'm previously iterating through $result
while ($i2=mysql_fetch_assoc($result)) {
$busnumber=$i2['busnumber'];
$busroute=$i2['route'];
echo "<div class='businfo'>";
if ($busroute='2'){ // I only want this to happen if $busroute=2
echo "Current Route = $busroute</br>";
echo "Bus Number : $busnumber </br>";
}
echo "</div>";
}
What I'm getting, however, it is echoing the same '$busroute' (2) but different '$busnumber' for each row as such:
Current Route = 2
Bus Number : 194
Current Route = 2
Bus Number : 196
Current Route = 2
Bus Number : 2002
Current Route = 2
Bus Number : 2010
Current Route = 2
Bus Number : 2013
The problem is that all of those bus numbers are not part of route 2. It is a listing of bus numbers from all routes. I only want it to perform the foreach loop if $routenumber=2.
Thanks again for the help :)
if ($busroute='2'){
The problem is that you're not checking whether it's equal to 2 here, you're assigning it to equal 2. Change it to this and you'll be fine:
if ($busroute=='2'){
$query = "SELECT * from foo";
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)) {
if ($row['route'] == 2) {
// do your stuff
}
}
I'm trying to make a commenting thread like Disqus has done. I'm having trouble setting up the logic in PHP to display the comments such that one can reply to each comment and those comments will then stay attached to each other.
here's my MySQL comments table:
comment_id comment item_id replied_to_id time
1 hello1 1 1 1:00pm
2 hello2 1 1 2:00pm
3 hello3 1 3 3:00pm
4 hello4 2 4 4:00pm
5 hello5 1 2 2:00pm
6 hello6 1 3 6:00pm
item_id is a column which indicates the parent item that the comments are discussing.
If I pull from my database all the comments with item_id=1, then I'm not sure how to thread them such that the comment_id and replied_to_id's are appropriately matched. For example, comment_id=2 should be matched to comment_id=1.
Here's my PHP:
<?foreach($comments as $row){
if($row->comment_id==$row->replied_to_id){
echo $row->comment."-".$row->time; //desired output: hello1-1:00pm
foreach($comments as $sub_row){
if($row->comment_id!=$sub_row->replied_to_id){
echo $sub_row->comment."-".$sub_row->time;// desired output: hello2-2:00pm
foreach($comments as $sub_sub_row){
if($row->comment_id!=$sub_sub_row->replied_to_id){
echo $sub_sub_row->comment."-".$sub_sub_row->time;// desired output: hello5-5:00pm
}
}
}
}
}
else{
echo $row->comment."-".$row->time; // desired output: hello3-3:00pm
}
}
This just looks wrong. There has got to be a better way to do this.
Simple demo, not necessarily the most optimal, but working:
function displayComments(array $comments, $parentId = null) {
foreach ($comments as $comment) {
if ($comment['replied_to_id'] == $parentId) {
echo $comment['comment'];
displayComments($comments, $comment['id']);
}
}
}
This assumes top-level comments have no replied_to_id (null). Your example with comment 1 replying to 1 doesn't make much sense.