Iterate list values from table - php

I have two tables, who are joined and the ID of each table and element underneath are similar.
parentID | objectName | subID ID| className| subName |
_____________________________ ________________________
84 | Test | 14 14| BOM | Test
84 | More | 16 14| PDF | Test
84 | Sub | 15 15| Schematics | Test2
I want to list the categoryname and the subID of the related elements. Several ObjectNames will have several related classes.
PHP code:
$objects = mysqli_query($con,"SELECT * from subobject");
$join = mysqli_query($con, "SELECT * FROM subrelation AS subrelation INNER JOIN subobject AS subobject ON subobject.subId = subrelation.ID;");
echo "<ul>";
while($obj = mysqli_fetch_array($objects) and $row = mysqli_fetch_array($join))
{
echo "<li>". $obj['objectName'];
echo "<ul>";
//ITERATION GOES HERE
if($obj['objectName'] == $row['subName'])
echo "<li>". "$row[className]" . "</li>";
//END OF ITTERATION
echo "</ul>";
echo "</li>";
}
echo "</ul>";
?>
and output list:
-Test
-BOM
-Sub
-Schematics
-More
under each field there are supposed to be more listed values.

It looks like you need to simplify your code a bit. My guess is that your problem is occurring because you have different amounts of rows in each result set. This makes your while loop exit when it finishes going through the smaller result set (probably $objects), even though there's still more elements in the larger set.
A solution is to sort the results of your query, use just one condition in your while loop, and keep track of which objectName you're currently on using a string $curr_objectName:
$join = mysqli_query($con, 'SELECT * FROM subrelation AS subrelation INNER JOIN subobject AS subobject ON subobject.subId = subrelation.ID ORDER BY subobject.objectName;');
$curr_objectName = '';
echo '<ul>';
while($row = mysqli_fetch_array($join)) {
$subName = $row['subName'];
if($subName != $curr_objectName)) {
if($curr_objectName != '') {
#close the previous list
#will be skipped on the first loop iteration
echo '</ul>';
echo '</li>';
}
#start a new list
$curr_objectName = $subName;
echo '<li>'. $obj['objectName'];
echo '<ul>';
} else {
echo '<li>'. $row['className'] . '</li>';
}
}
echo '</ul>';

Related

Loop through php array issues

I'm sure I've been staring at this WAY too long, so asking for a lifeline.
I'm pulling data from a MySQL database. In particular this:
$category[] = "$row->category";
$issue[] = "$row->issue";
I need to cycle through the data. There are 6 categories in total and could be any number of issues for each category.
I would like to echo the data for each row as follows:
Category 1
Issue 1a
Issue 1b
Issue 1c
Category 2
Issue 2a
Issue 2b
Category 3
Issue 3a
Issue 3b
Issue 3c
Issue 3d
Issue 3e
I probably need more sleep, but I cannot seem to cycle through this properly. Any help would be appreciated.
$stmt = $pdo->prepare("SELECT * FROM project INNER JOIN data1 ON project.p_key = data1.p_key_project WHERE data1.p_key_project=? AND data1.archived=? ORDER BY data1.category, data1.updated DESC");
$stmt->execute(array($passed_key,'n'));
while ($row = $stmt->fetchObject()) {
$cust[] = "$row->cust_name";
$p_key[] = "$row->p_key";
$pid[] = "$row->pid";
$account_key[] = "$row->account_key";
$p_key_data1[] = "$row->p_key_data1";
$date[] = "$row->date";
$updated[] = "$row->updated";
$category[] = "$row->category";
$ryg[] = "$row->ryg";
$issue[] = "$row->issue";
$proposed_resolution[] = "$row->proposed_resolution";
$action_items[] = "$row->action_items";
$owner[] = "$row->owner";
$status[] = "$row->status";
}
PDO version based on updates we've been talking about:
assume $issues is a multidimensional array of issues and categories you could do. i.e. $issue[] = "$row->issue, $row->category";
$numOfItems = count($issue); //counts number of times for should be run
for ($row = 0; $row < $numofItems; $row++) {
echo $issues[$row][$row] . "</br>";
$i=0;
while ($issues[$i][$row] == $issues[$row][$row]) {
echo $issues[$i][$row] . "</br>";
$i++;
} }
This is freehand - but it should work
OLD ANSWER BELOW
If you copy and paste the Database Schema (or a part of it) that would be helpful to see how Categories and Issues are related. Not seeing the exact relationship, I think this is probably how your database is structured
so lets that $category[] = "$row->category"; populates categories; now you have to match issues to each category. I assume that a row in your database has a category assigned to each issue. i.e. your database looks like
ID | Category | Issue
1 | Pizza | Bad
2 | Pizza | Good
If thats the case then below should work
foreach ($category as $key => $value) {
$query = mysqli_query($con,"SELECT * FROM project INNER JOIN data1 ON project.p_key = data1.p_key_project WHERE data1.p_key_project=? AND data1.archived=? AND data1.category='$value' ORDER BY data1.category, data1.updated DESC"); //value is the individual category
echo $value . "</br>";
while($row = mysqli_fetch_array($query)) {
echo $row['issue'] . '</br>';
}
echo "</br>"; //adds an extra space between categories
}
Updated to include your specific query

How to display comments in a nested way with parent ID

I have a table comments, thats look like this, added some mockup content as well:
+------------+---------+----------+-------------------+------------------------------------+---------------------------+
| comment_id | user_id | movie_id | comment_parent_id | comment_content | comment_creation_datetime |
+------------+---------+----------+-------------------+------------------------------------+---------------------------+
| 26 | 1 | 16329 | 0 | Första | 2016-01-24 10:42:49 |
| 27 | 1 | 16329 | 26 | Svar till första | 2016-01-24 10:42:55 |
| 28 | 1 | 16329 | 26 | Andra svar till förta | 2016-01-24 10:43:06 |
| 29 | 1 | 16329 | 28 | Svar till "andra svar till första" | 2016-01-24 10:43:23 |
+------------+---------+----------+-------------------+------------------------------------+---------------------------+
Im trying to display the comments Reddit style, like this image:
Im trying to fetch all comments SELECT * FROM comments WHERE movie_id = :movie_id ORDER BY comment_creation_datetime DESC and then recursively echo them out.
I have tried a bunch of foreachloops, but none is working as expected
foreach($this->comments as $value){ ?>
<div class="comment">
Comment content <?php echo $value->comment_content; ?>
<?php if($value->comment_parent_id > 0){
foreach($value as $sub_comment){ ?>
<div class="comment">
comment comment on comment: <?php echo $value->comment_content; ?>
</div>
<?php }} ?>
</div>
<?php }
My question:
How do I echo out the comments in a nested Reddit style with foreach loop?
You need to both make a list of root comments, and hierarchically organize all of them. You can do both in one go:
$roots = [];
$all = [];
foreach($comments as $comment)
{
// Make sure all have a list of children
$comment->comments = [];
// Store all by ID in associative array
$all[$comment->comment_id] = $comment;
// Store the root comments in the roots array, and the others in their parent
if(empty($comment->comment_parent_id))
$roots[] = $comment;
else
$all[$comment->comment_parent_id]->comments[] = $comment;
}
// Check it's all done correctly!
print_r($roots);
You presorted the list by date, that's preserved in this approach. Also, as you only reorganized by reference this is lightning fast, and ready to be used in templating engines or anything - no need to print out inline like the other answers.
Working with the adjacency list model can be more problematic with SQL. You need to retrieves all the rows with a single query and store a reference of any parent's child in a lookup table.
$sth = $pdo->prepare("SELECT * FROM comments WHERE movie_id = ? ORDER BY comment_creation_datetime DESC");
$sth->execute([$movie_id]);
$comments = $sth->fetchAll(PDO::FETCH_ASSOC);
$lookup_table = [];
foreach ($comments as $comment_key => $comment) {
$lookup_table[$comment['comment_parent_id']][$comment_key] = $comment['comment_id'];
}
Now you can display them with
function recursive_child_display($comments, $lookup_table, $root = 0, $deep = 0)
{
if (isset($lookup_table[$root])) {
foreach ($lookup_table[$root] as $comment_key => $comment_id) {
// You can use $deep to test if you're in a comment of a comment
echo '<div class="comment">';
echo 'Comment content ', $comments[$comment_key]['comment_content'];
recursive_child_display($comments, $lookup_table, $comment_id, $deep+1);
echo '</div>';
}
}
}
Example:
// display all the comments from the root
recursive_child_display($comments, $lookup_table, 0);
// display all comments that are parent of comment_id 26
recursive_child_display($comments, $lookup_table, 26);
I would use some recursive function, you start with the ones with parent_id == 0 and recursively print all those who are their direct children.
This code is not tested, but you can get the idea:
function printComment($comment, $comments)
{
foreach($comments as $c)
{
if($c->parent_id == $comment->comment_id)
{
$output .= "<li>".printCommment($c)."</li>";
}
}
$output = "<ul>".$comment->comment_content."</ul>".$output;
return $output;
}
foreach($this->comments as $comment)
{
if($comment->parent_id == 0)
{
echo printComment($comment,$this->comments);
}
}

Craft calculator loop

I'm trying to do a craft calculator for a game.
I have a database who looks like this :
Crafts :
id item_id item_name amount
3 1895 a 5
8 2486 c 1
Craft_materials :
id craft_id item_id item_name amount
1 3 2486 c 15
2 3 5302 d 23
3 3 5698 e 2
4 8 2014 f 3
And here is my query to retrieve the data :
$craftProduct = $db->query("SELECT * FROM crafts WHERE item_id=$item");
$craftProduct->setFetchMode(PDO::FETCH_OBJ);
$product = $craftProduct->fetch();
$craftID = $product->id;
$craftMaterial = $db->query("SELECT * FROM craft_materials WHERE craft_id=$craftID");
$craftMaterial->setFetchMode(PDO::FETCH_OBJ);
echo '<ul>';
echo '<li>'.$product->item_name.' ('.$product->amount.')</li>';
echo '<ul>';
while($material = $craftMaterial->fetch()){
echo '<li>'.$material->item_name.' ('.$material->amount.')</li>';
}
echo '</ul>';
echo '</ul>';
What I want to do is take the material id and check if it corresponds with a craft. If it does, I want to show the material needed to craft it.
I want something which looks like this :
- a (5)
- c (15)
- f (3)
- d (23)
- e (2)
However, I don't know how to do the loop. Can anyone help me?
Here is a basic recursion setup:
function render_item($item_id) {
$product = fetch_item($item_id); // select from crafts where item_id = $item_id
$children = "";
foreach (fetch_children($product->id) as $child_id) { // select from craft_mats where craft_id = $product->id
$children .= render_item($child_id);
}
echo "<li>" . $product->item_name . "<ul>" . $children . "</ul></li>";
}
echo "<ul>" . render_item(1895) . "</ul>"

How to retrieve liker id based on ques_id?

Here is my database:
id | liker | ques_id
1 | 15 | 2342
2 | 22 | 2342
3 | 22 | 2311
4 | 15 | 2389
What I need to get is all the liker's who have liked ques_id. So the result should look something like this:
Question 2342 has been liked by 15 and 22.
Question 2311 has been liked by 22 and so on
My current code produces separate row for each liker and ques_id:
$sqlq=mysql_query("SELECT * FROM likes");
while($rowq=mysql_fetch_array($sqlq)){
$qid=$rowq['ques_id'];
$sql=mysql_query("SELECT * FROM likes where ques_id='$qid'");
$num=mysql_num_rows($sql);
$cont='';
while($row=mysql_fetch_array($sql)){
$liker=$row['liker'];
$cont .="$qid being liked by $liker<br>";
}
echo $cont;
}
I haven't tested this but it should get you started:
$sqlq=mysql_query("SELECT DISTINCT(ques_id) FROM likes");
$cont='';
while($rowq=mysql_fetch_array($sqlq)){
$qid=$rowq['ques_id'];
$sql=mysql_query("SELECT * FROM likes where ques_id='$qid'");
$num=mysql_num_rows($sql);
$row=mysql_fetch_array($sql)
$cont .= "$qid being liked by $liker ";
while($row=mysql_fetch_array($sql)){
$liker=$row['liker'];
$cont .= " and $liker";
}
$cont .= ".<br>";
}
echo $cont;
You need no second query to DB, it enough iterate only first result.
For example, you may collect all the likers, that match a specific ques_id in a assoc array with keys are ques_id, like this:
$mathces = array();
$sqlq=mysql_query("SELECT * FROM likes");
while($rowq=mysql_fetch_array($sqlq)){
$qid=$rowq['ques_id'];
$liker=$rowq['liker'];
$matches[ $qid ][] = $liker;
}
Then, you may foreach $mathces array and build you string.
foreach ($matches as $qid => $likers) {
$cont .= "$qid being liked by " . implode(' and ', $likers );
if (count($likers) == 1)
$cont .= ' and so on';
echo "$cont<br>";
}
I didn't test my code. It need to additional validations (e.g. for $linkers in second loop)
SELECT GROUP_CONCAT(liker), ques_id FROM likes GROUP BY ques_id
That will pull each liker grouped together for each ques_id.
You then only have to process the rows returned.
You should steer clear of the mysql extension as it is deprecated; use PDO or mysqli instead.
$sql = 'SELECT GROUP_CONCAT(liker) as likes, ques_id FROM likes GROUP BY ques_id';
foreach ($conn->query($sql) as $row) {
printf('Question %s is liked by %s', $row['ques_id'], $row['likes']);
}

Group by common id

I am trying to fetch data from my database and would like to group common values in the column called order_ids by that id.
This is the state I currently get my data in
Order_Id | Product Name
-------------------------------
10001 | iPhone 5
10001 | Blackberry 9900
10002 | Galaxy S
10003 | Rhyme
10004 | Google Nexus
10005 | Razr
10006 | iPad Air
And this is the state I want to get it in
Order_Id | Product Name
-------------------------------
10001 | iPhone 5
Blackberry 9900
10002 | Galaxy S
10003 | Rhyme
10004 | Google Nexus
10005 | Razr
10006 | iPad Air
Here is how I get the result in my controller file
foreach($results_query as $results_custom) {
$this->data['result_custom'][] = array(
'model' => $results_custom['product_name'],
'order_number' => $results_custom['order_id']
);
}
Here is how I display it in my view file
<?php foreach ($results_custom as $result) { ?>
<li><?php echo $result['model']; ?></li> <br />
<li><?php echo $result['order_number']; ?></li><br />
<?php } ?>
Is it possible to get my data to display like that or in that state by using SQL or PHP? Please let me know if you want to see my query as well.
In php would be easier to do it. As I don't have PHP enviroment to test it I will show you some logic to do it. Not necessarily working code. Thats because you didn't provide what you did
<?
$sql = "select order_id, product name from ..... order by order_id"// rest of sql code ....
//here you iterate your results
$previousId = ""; //var to store previous id
while( $fetch... ){
if ( $fetchedID != $previousId ){
echo $fetchedId . "-" . $fetchedProductName;
}else{
echo $fetchedProductName;
}
$previousId = $fetchedID;
}
?>
This should do.
As you updated your code this is a solution for you:
<?php
$lines = ""; //to make code cleaner;
$previousModel = "";
foreach ($results_custom as $result) {
if ( $previousModel != $result['model'] ){
$line .= "<li>" . $result['model'] . "</li>";
}else{
$line .= "<li></li>";
}
$line .= "<li>" . $result['model'] . "</li><br />";
$previousModel = $result['model'];
}
echo $line;
<?php } ?>
I suggest you to use GROUP_CONCAT for getting the result
You try as follows
SELECT order_id,GROUP_CONCAT(product_name) as product_name FROM your_table GROUP BY order_id
Just look at this http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
Note : GROUP_CONCAT has a size limit. Check this link for more MySQL and GROUP_CONCAT() maximum length
you might be able to accomplish this in just MySQL, but it might be easier if you just create a php loop. most people prefer a foreach loop, but I like while loops:
$orderid = "number";
$order_query = mysql_query("SELECT * FROM ordertable WHERE Order_Id = '$orderid'");
while($order_data = mysql_fetch_array($order_query)){
$ordername = stripslashes(mysql_real_escape_string($order_data['Product Name']));
echo $ordername.'<br />';
}
if you need this for ALL orders you could remove searching for a specific order:
$order_query = mysql_query("SELECT * FROM ordertable ORDER BY Order_Id ASC");
while($order_data = mysql_fetch_array($order_query)){
$orderid = mysql_real_escape_string($order_data['Order_Id']);
$ordername = stripslashes(mysql_real_escape_string($order_data['Product Name']));
echo 'ID#: '.$orderid.' - '.$ordername.'<br />';
}

Categories