I have a comments page on my website, in which a MySQL query fetches the all the data from a ‘comment’ table, and for each row it encounters a simple table is printed to display the comment. Simple enough.
I want to extend this so that comments can be nested inside of each other though, and to do this I’ve given the ‘comment’ table a column to specify the ID of the comment each one should be nested inside.
Now I have one query which returns all top-level comments (those whose ‘parent’ is “0”), and for each row encountered a table is printed. After the table is printed, a second query fetches all comments from the table whose parent is equal to the ID of the comment in the current row. If one is found then then the file includes itself to push it through and continue iterating through the table data.
This almost works, it’s able to keep ‘digging down’ to find the children of comments, the problem is that it only does this with the path encountered, and once it reaches the end it jumps straight back up to continuing the top level of comments, so any ‘siblings’ are missed, i.e. comments 4 and 5 below:
Here’s a highly trimmed down version of my code so that you can more easily understand what’s going on:
//File: PrintComments.php
$commentQuery = "SELECT * FROM comment WHERE parent = 0";
$commentResult = mysql_result($commentQuery)
while ($row = mysql_fetch_array($commentResult))
{
echo '[Table containing comment data]';
$childQuery = "SELECT * FROM comment WHERE parent = $commentID";
$childResult = mysql_result($childQuery)
while ($row2 = mysql_fetch_array($childResult))
{
include("PrintComments.php");
}
}
Any idea of how I can properly handle this? I’ve tried for hours with no results, and all other solutions I’ve come across on the web seem to be considerably more complex.
Brilliant! The solution that you provided works perfectly; it now does exactly what I wanted, so thank you very much!
The problem that you pointed out with my use of the ‘include’ seems very obvious to me now, I’m not sure how I missed it to begin with but it caused my brain to fry as I tried to work around it. I won’t be making that mistake again.
If you include a file, it’s the same as copy/pasting the contents of that file in place of the include statement, so I could do (for example, it’s not going to work, just to make a point):
//File: PrintComments.php
$commentQuery = "SELECT * FROM comment WHERE parent = 0";
$commentResult = mysql_result($commentQuery)
while ($row = mysql_fetch_array($commentResult))
{
echo '[Table containing comment data]';
$childQuery = "SELECT * FROM comment WHERE parent = $commentID";
$childResult = mysql_result($childQuery)
while ($row2 = mysql_fetch_array($childResult))
{
// replaced include with actual code
$commentQuery = "SELECT * FROM comment WHERE parent = 0";
$commentResult = mysql_result($commentQuery)
while ($row = mysql_fetch_array($commentResult))
{
echo '[Table containing comment data]';
$childQuery = "SELECT * FROM comment WHERE parent = $commentID";
$childResult = mysql_result($childQuery)
while ($row2 = mysql_fetch_array($childResult))
{
include("PrintComments.php");
}
}
// end "include"
}
}
Now look carefully. The outermost while defines a $row and iterates those. It then finds comment2, and sees that that there comments to that comment, and does another query that overwrites $row of the outermost while, so if the include is done, $row is changed, and you code can’t find comment4 and comment5 anymore, because they’re not longer in $row.
I would solve it using a function, so $row stays within the function scope and a subsequent call can not overwrite the value of a former call.
Something like this:
function showComments($parent = 0)
{
$commentQuery = "SELECT * FROM comment WHERE parent = ".mysql_real_escape_string($parentId);
$commentResult = mysql_query($commentQuery)
while ($row = mysql_fetch_array($commentResult))
{
echo '[Table containing comment data]';
showComments($row['commentID']);
}
}
showComments();