Displaying Threaded Messages

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
waradmin
Forum Contributor
Posts: 240
Joined: Fri Nov 04, 2005 2:57 pm

Displaying Threaded Messages

Post by waradmin »

I am just messing around with various things for no real reason, and one thing I wanted to do was implement a threaded message display. IE:

Code: Select all

 
Parent (parent_id = 0, id = 1)
-- Child (parent_id = 1, id = 3)
------ Child (parent_id = 3, id = 4)
-- Child (parent_id = 1, id = 6)
------ Child (parent_id = 6, id = 8)
---------- Child (parent_id = 8, id = 2)
Parent (parent_id = 0, id = 5)
Parent (parent_id = 0, id = 11)
Parent (parent_id = 0, id = 15)
-- Child
 
I was thinking this would be simple. However my brain is at a loss as to how to loop and get this displayed properly.

Values are in a database. Fields:

Code: Select all

id | parent_id | content | name
Where:
id = auto_inc number
parent_id = what id is the root of this comment. If 0, it is a parent. If > 0 it ties it to the parent comment. In the above example, the ID's were numbers I just pulled out of my hat. I did that to show that the childs parent_id = the parents id
content = what is in the thread
name = who made the comment

I have tried a few things with no success. Styling it is easy, but getting the messages to display in the right order is the hard part. Why? Because anyone can reply to any thread at any time thus the database cannot be queried and directly outputted. Chances are arrays need to be created to handle this stuff, but I don't have ideas on how to implement this.

Any help would be greatly appreciated.
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: Displaying Threaded Messages

Post by requinix »

waradmin wrote:Because anyone can reply to any thread at any time thus the database cannot be queried and directly outputted.
Care to elaborate on the problem with that?

One word: recursion. Depending how you want the output it can be easy or it can be hard(er).
Simple example using <UL> and <LI> lists:

Code: Select all

<?php
 
// Given an ID number create a <UL> list of its children
function showThreads($parent) {
    $children = mysql_query("SELECT `id`, `parent_id`, `name` FROM `threads` WHERE `parent_id` = " . intval($parent) . " ORDER BY `id`");
    if (mysql_num_rows($children) == 0) return; // no results
    
    echo "<ul>";
    while (list($id, $parent_id, $name) = mysql_fetch_array($children)) {
        echo "<li>", htmlentities($name);
        showThreads($id);
        echo "</li>";
    }
    echo "</ul>\n";
}
 
showThreads(0);
 
?>
User avatar
waradmin
Forum Contributor
Posts: 240
Joined: Fri Nov 04, 2005 2:57 pm

Re: Displaying Threaded Messages

Post by waradmin »

Thank you much for the reply, I am going to try that tomorrow when I am not studying for exams. I had a feeling the solution would be recursive. I am not good at visualizing recursive solutions, I struggled with recursion throughout CS 1 and 2. From what I am gathering here, there will be Parents + Children queries performed, correct? Is it good practice to have db queries executed in a recursive function (does it cause excess load, or no? I have no idea I am just speculating).

I was ripping my head open trying to find a way to do a single query, store the values in a few arrays, then recursively pull from them from the array to keep the query count on the DB at a minimum. But again, I am speculating on everything. If its completely legitimate to use queries in recursive functions that may be called 2 times, or 2,000 times then thats all good in my book. I am learning a lot here (and love learning programming concepts) so if anyone could weigh in on that topic I am all ears.
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: Displaying Threaded Messages

Post by requinix »

waradmin wrote:Thank you much for the reply, I am going to try that tomorrow when I am not studying for exams. I had a feeling the solution would be recursive. I am not good at visualizing recursive solutions, I struggled with recursion throughout CS 1 and 2. From what I am gathering here, there will be Parents + Children queries performed, correct? Is it good practice to have db queries executed in a recursive function (does it cause excess load, or no? I have no idea I am just speculating).

I was ripping my head open trying to find a way to do a single query, store the values in a few arrays, then recursively pull from them from the array to keep the query count on the DB at a minimum. But again, I am speculating on everything. If its completely legitimate to use queries in recursive functions that may be called 2 times, or 2,000 times then thats all good in my book. I am learning a lot here (and love learning programming concepts) so if anyone could weigh in on that topic I am all ears.
For N things there will be N separate queries. It's maybe not the best solution but it's the simplest.

(One of) the best would be like what you said: buffer everything into an array, sort the array, and run a recursive function over it. But that means consuming memory, and lots of things will mean lots of memory used.

For both methods, it'd greatly help if you would (a) only show X threads at a time, and/or (b) only show the first Y levels of the thread.
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Re: Displaying Threaded Messages

Post by alex.barylski »

The easiest approach is to use a table like so:

Code: Select all

pkid, ppid, subject, message
ppid points to the parent of the item, ZERO would mean a root item or in this case a "New" topic.

Now to display your messages in a threaded fashion you would use recursion (can be done more efficnetly with a while loop and state variables but recursion is much easier to comprehend and implement).

Code: Select all

function select_threads($puid)
{
  static $depth = 0;
  $sql = "SELECT * FROM table WHERE puid = $puid";
  $res = mysq_query($sql);
 
  for($i=0; $i<mysql_num_rows($res); $i++){
    $row = mysql_fetch_assoc($res);
 
    $padding = $depth * 10;
    echo "<div style='padding-left: $paddingpx'>$subject - $message</div>";
    
    $depth++;
    return select_threads($row['puid']);
  }
  
  $depth--; 
}
You then get the ball rolling by calling the function like so:

Code: Select all

select_threads(0); // Start at the root messages.
Probably buggy but should give you the idea as to how it's done.
User avatar
waradmin
Forum Contributor
Posts: 240
Joined: Fri Nov 04, 2005 2:57 pm

Re: Displaying Threaded Messages

Post by waradmin »

PCSpectra wrote:The easiest approach is to use a table like so:

Code: Select all

pkid, ppid, subject, message
ppid points to the parent of the item, ZERO would mean a root item or in this case a "New" topic.

Now to display your messages in a threaded fashion you would use recursion (can be done more efficnetly with a while loop and state variables but recursion is much easier to comprehend and implement).

Code: Select all

function select_threads($puid)
{
  static $depth = 0;
  $sql = "SELECT * FROM table WHERE puid = $puid";
  $res = mysq_query($sql);
 
  for($i=0; $i<mysql_num_rows($res); $i++){
    $row = mysql_fetch_assoc($res);
 
    $padding = $depth * 10;
    echo "<div style='padding-left: $paddingpx'>$subject - $message</div>";
    
    $depth++;
    return select_threads($row['puid']);
  }
  
  $depth--; 
}
You then get the ball rolling by calling the function like so:

Code: Select all

select_threads(0); // Start at the root messages.
Probably buggy but should give you the idea as to how it's done.
This worked great, I just had to remove the return statement to make it function properly. Thanks!
Post Reply