Recursive tree traversal with mysql through PHP - php

I am creating a questionnaire for a client that requires the questions to be organized by 3 layers of levels. I've successfully created the U.I. however I've been trying for the last 3 hours to pull data from a database in such a way that everything loads in the right place. The database is organized like so by the client so I have no control over it:
id description parentId
1 Level 1 0
2 Level 2 0
3 Level 1a 1
4 Level 1b 1
5 Level 1a1 3
I have found a similar question to mine on the site but when I attempted it's solution I got the following on repeat infinetly:
Code:
function makeList($par_id = 0) {
//your sql code here
$result = mysql_query("SELECT * FROM pB_test WHERE parentId = $par_id");
$pages = mysql_fetch_array( $result );
if (count($pages)) {
echo '<ul>';
foreach ($pages as $page) {
echo '<li>', $page['description'];
makeList($page['parentId']);
echo '</li>';
}
echo '</ul>';
}
}
makeList();
Output:
1
3
5
5
l
l
3
5
5
l
l
3
5
5
l
l
3
5
5
l
l
Does anyone know how to fix this and what the issue is exactly? Cheers

it's not good to call mysql server and fetch result each time
what if you have over 100 rows? or 200+
use this to query only once:
$result = mysql_query("SELECT * FROM test");
$arrs = array();
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$arrs[] = $row;
}
function build_tree($arrs, $parent_id=0, $level=0) {
foreach ($arrs as $arr) {
if ($arr['parent_id'] == $parent_id) {
echo str_repeat("-", $level)." ".$arr['name']."<br />";
build_tree($arrs, $arr['id'], $level+1);
}
}
}
build_tree($arrs);
common example for table
id name parent_id

Do this recursivly:
function printChildQuestions($parentid) {
$sql="SELECT * FROM pB_test WHERE parentID=$parentid";
$result=mysql_query($sql);
$i=0;
while (true) {
$row=mysql_fetch_array($result);
if (!$row) break;
if ($i==0) echo "<ul>";
$i=1;
echo '<li>'.$row['id'].' '.$row['description'].' '.$row['parentId'].'</li>';
printChildQuestions($row['id']);
}
if ($i>0) echo '</ul>';
}
printChildQuestions(0);

Related

Assigning increment number to <li></li> value

I am displaying list of category from MySQL database and while displaying those category I am trying to assign the value of each item from 2 to 9. So when all (8 row in total) category displayed, the value should start from 2, 3, 4, 5 .... 9.
Here is what I did in my coding :
$select_cat = "SELECT * FROM tblcat";
$result_cat = $conn->query($select_cat);
if ($result_cat->num_rows > 0)
{
while($row_disp_cat = mysqli_fetch_assoc($result_cat))
{
for ($id = 2; $id <=9; $id++)
{
echo '<li><a id="'.$id.'">'.$row_disp_cat['catName'].'</a></li>';
}
}
}
With above code I am getting the value looping 8 times of 2-9
I hope it help.
$select_cat = "SELECT * FROM tblcat";
$result_cat = $conn->query($select_cat);
if ($result_cat->num_rows > 0)
{
$id = 2;
while($row_disp_cat = mysqli_fetch_assoc($result_cat))
{
echo '<li><a id="'.$id.'">'.$row_disp_cat['catName'].'</a></li>';
$id++;
}
}
I recommend you use PDO for reasons beyond the scope of this answer which you should investigate yourself for the fun of it. However, you should remove the for loop and use the Primary Key of your tblcat entries as the $id so you can find them after your user has selected an option. If the $id has to have a value between 2 and 8 then you should use #Hossein's suggestion.

bug nested foreach loops

I have a problem with my code, it two nested foreach loops:
$message = mysqli_query($mysqli, "SELECT * FROM messages where pseudo ='".$Pseudo."'");
while ($data = mysqli_fetch_assoc($message)) {
$items[] = $data;
}
$items = array_reverse($items ,true);
foreach($items as $item) {
echo"".$item['msg']."";
$commentaires = mysqli_query($mysqli, "SELECT * FROM commentaires where msg ='".$item['msg']."' and profil ='".$item['pseudo']."'");
while($row = $commentaires->fetch_array()) {
$rows[] = $row;
}
foreach($rows as $row) {
$abc = $row[0];$commen = $row[3];
echo "$abc : $commen";
}
}
so i've 2 entries in "messages" and 4 entries for "commentaires" 2 for the first entry of "messages" and 2 for the second. I want that :
message1
-commentaire 1
-commentaire 2
message2
-commentaire 3
-commentaire 4
and this is what i have :
message1
-commentaire 1
-commentaire 2
message2
-commentaire 1
-commentaire 2
-commentaire 3
-commentaire 4
i've search during 2 hours i don't have found a solution in mysqli :(
(when i do
mysqli_data_seek($commentaires ,0);
that don't change anything)
sorry for my bad English :c
Im pretty sure that this:
while($row = $commentaires->fetch_array()){$rows[] = $row;}
appends rows to existing array..
which means you have to clear $rows before appending new data to it, if you want it to work as written.
I'm no PHP shark, but I do believe
unset($rows);
would do the trick

how to auto-increment with 1 and append decimal if row value like 1st row else 2

i have this code to generate a report joining two table.
$agebracket= $_POST['age_bracket']; //coming from dropdown list
$sql=mysql_query("select qshortcode from question_details where pans1 like '%$agebracket%'");
while($row=mysql_fetch_array($sql)){
$utility[] = preg_replace('/[0-9]+/','',$row['qshortcode']);
}
$slno=0;
for($i=0;$i<count($utility);$i++) {
$last=""; //as suggested
$check=mysql_query("select q.qshortcode,q.qcode,q.question,p.paid_rev from question_details q left outer join paid_response p on q.qcode=p.qno where q.qshortcode like '$utility[$i]%' group by q.qcode");
while($qscode=mysql_fetch_array($check)) {
if($last =substr($qscode['qcode'],strlen($last))) {
$last = $qscode['qcode'];
$slno++;
$slid = $slno ;
} else {
$slid .= ".1";
}
echo "<tr>";
echo "<td>".$slid.' '."</td>";
echo "<td>".$qscode['qshortcode'].' '."</td>";
echo "<td>".$qscode['qcode'].' '."</td>";
echo "<td>".$qscode['question'].' '."</td>";
echo "<td>".$qscode['paid_rev']."<br></td>";
echo "</tr>";
}
}
echo "</table>";
this generates this report fetching from two tables with left outer join to also get the blank revenue
SL-No Qcode Question Revenue
1 test whatever
1.1 test_1 zzz
2 test_2 xxx something //here it is becoming 2 but it should be 1.1.1
3 abc vvv
3.1 abc1 khkhk something
now actually i want to auto-increment SL-No with 1 then if qcode matches like the 1st row qcode it will be 1.1 then 1.1.1 then when it dont matches it will be 2. like the report will be like
SL-No Qcode Question Revenue
1 test whatever
1.1 test_1 zzz
1.1.1 test_2 xxx something
2 abc vvv
2.1 abc1 khkhk something
I would do something like this (untested code):
$slno=0;
[...] // for loop omitted, just starting at 0 instead of 1, to increment properly after.
$last="-1"; // To avoid comparing two empty lines at first pass, which will obvisouly be alway true, sorry.
while ([mysql query ....]) {
if ($last != substr($qscode['qcode'],0, strlen($last))) {
$last = $qscode['qcode'];
$slno++;
$slid = strval($slno)
} else {
$slid .= ".1"
}
echo "<tr>";
echo "<td>".$slid.' '."</td>";
echo "<td>".$qscode['qshortcode'].' '."</td>";
[...] // rest omitted
}

Create Unordered List from View Query?

I have a query that will produce the results I need:
SELECT SHOW_NAME, YEAR, CLASS_NAME FROM vwhandlerresults WHERE HANDLER_ID = $gethandlerid ORDER BY YEAR DESC
SHOW_NAME YEAR CLASS_NAME
Show 1 2013 Class 1
Show 1 2013 Class 2
Show 2 2013 Class 1
Show 3 2012 Class 1
etc. etc.
I want to create a 3 level unordered list in php so that I can have something similar to the following:
2013
Show 1
Class 1
Class 2
Show 2
Class 1
2012
Show 3
Class 1
I have searched and searched, and can't get my head around it at all. I managed it to one level (Year -> Show). From searching, I get the feeling I might need an array?
Thanks
Gray
Technically, you don't need to build an array in advance. You can do it as the data is fetched from the DB using a simple-ish "state machine".
echo '<ul>';
$oldyear = null;
$oldshow = null;
while($row = fetch_result($result)) { // grab a row of DB data
if ($oldyear != $row['year']) {
echo "<li>{$row['year']}<ul>";
}
if ($oldshow != $row['show']) {
echo "<li>{$row['show']}<ul>";
}
echo "<li>{$row['class']}</li>";
}
NOTE: this will NOT work as is, it's just to give you a general idea of what'd be needed if you choose to go this route
However, if you choose to go with the array route, it'll be a bit more work upfront, but vastly simplify the output logic:
$data = array();
while($row = fetch_row($result)) {
$year = $row['year'];
$show = $row['show'];
$data[$year][$show][] = $row['class'];
}
echo '<ul>'
foreach($years as $year => $shows) {
echo '<li>', $year, '<ul>';
foreach($shows as $show) {
echo '<li>$show<ul>';
foreach ($show as $class) {
echo '<li>', $class, '</li>';
}
echo '</ul>';
}
echo '</ul>';
}
echo '</ul>';

php mysql - echo clear division after 3rd result

I echo results in DESC order from MySQL table with while loop. I've pagination system implemented already and its size is 9 records per page. The problem is, that if I do:
// ECHO CSS BREAK
if($row['id'] % 3 == 0){
echo '<li class="clear"></li>';
}
// SHOW VIDEOS
while($row = mysql_fetch_array($result)){
echo '<li>...echo code...</li>';
// problem = implement that echo css break in ASC order
}
Use a loop variable, e.g.
$i = 0;
Then instead of
if ($row['id'] % 3 == 0) {
do
if (++$i % 3 === 0) {
This makes sure it always happens are the third [sixth, ninth, ...] time.
You may want to get arbitrary rows from the database at another point in time, or shuffle the results -- relying on row IDs is not a good idea.
Is this what you are looking to implement?
// SHOW VIDEOS
while($row = mysql_fetch_array($result)){
if($row['id'] % 3 == 0){
echo '<li>...echo code...</li>';
echo '<li class="clear"></li>';
} else {
echo '<li>...echo code...</li>';
}
}

Categories