Reputation: 3523
I would like to diplay comments on my site like this:
<li>Parent
<ul>
<li>child one</li>
<li>child two
<ul>
<li>grandchild</li>
<li>other grandchild</li>
</ul>
</li>
</ul>
<li>Another parent with no children</li>
<li>
I have read the following article, however it doesn't use <li>
. So is there a way to display comments like I've done before with an array like so? Thanks.
$comments = array(
array('id'=>1, 'parent_id'=>NULL, 'text'=>'Parent'),
array('id'=>2, 'parent_id'=>1, 'text'=>'Child'),
array('id'=>3, 'parent_id'=>2, 'text'=>'Child Third level'),
array('id'=>4, 'parent_id'=>NULL, 'text'=>'Second Parent'),
array('id'=>5, 'parent_id'=>4, 'text'=>'Second Child')
);
Upvotes: 4
Views: 5347
Reputation: 15550
I asssume your comment table has id, parent_id, comment, ... and my suggestion goes like this;
Select you comments like;
$sql = "SELECT *FROM comments ORDER BY id DESC";
$rows = mysql_query($sql);
And next step is array operations.You can see the following code below and try working demo here;
$rows = your_select_result;//I assumed that you have done these stuffs
$comments = $row;
/**
This is test data, please remove this array while you are
running own application.Since you will use the data one you get your db
**/
$comments = array(
1 => array('id' => 1, 'parent_id' => 0, 'childs' => array()),
2 => array('id' => 2, 'parent_id' => 0, 'childs' => array()),
3 => array('id' => 3, 'parent_id' => 0, 'childs' => array()),
5 => array('id' => 5, 'parent_id' => 0, 'childs' => array()),
11 => array('id' => 11, 'parent_id' => 0, 'childs' => array()),
17 => array('id' => 17, 'parent_id' => 0, 'childs' => array()),
23 => array('id' => 23, 'parent_id' => 0, 'childs' => array()),
28 => array('id' => 28, 'parent_id' => 0, 'childs' => array()),
4 => array('id' => 4, 'parent_id' => 1, 'childs' => array()),
6 => array('id' => 6, 'parent_id' => 1, 'childs' => array()),
8 => array('id' => 8, 'parent_id' => 2, 'childs' => array()),
9 => array('id' => 9, 'parent_id' => 2, 'childs' => array()),
7 => array('id' => 7, 'parent_id' => 3, 'childs' => array()),
12 => array('id' =>12, 'parent_id' => 7, 'childs' => array()),
13 => array('id' => 13, 'parent_id' => 12, 'childs' => array()),
);
/** Comment prepare start */
foreach ($comments as $k => &$v) {
if ($v['parent_id'] != 0) {
$comments[$v['parent_id']]['childs'][] =& $v;
}
}
unset($v);
foreach ($comments as $k => $v) {
if ($v['parent_id'] != 0) {
unset($comments[$k]);
}
}
/** Comment prepare end */
//Your indent pattern
function indent($size) {
$string = "";
for ($i = 0; $i < $size; $i++) {
$string .= "#";
}
echo $string;
}
function printComments($comments, $indent = 0) {
foreach ($comments as $comment) {
echo indent($indent + 1).' I am comment '.$comment['id']."\n";
if (!empty($comment['childs'])) {
printComments($comment['childs'], $indent + 1);
}
}
}
printComments($comments);
For demo please see here
Upvotes: 4
Reputation: 1345
This function will only need the parent_id
and id
key present in each comment's array.
$comments = array(
array('id'=>1, 'parent_id'=>NULL, 'text'=>'Parent'),
array('id'=>2, 'parent_id'=>1, 'text'=>'Child'),
array('id'=>3, 'parent_id'=>2, 'text'=>'Child Third level'),
array('id'=>4, 'parent_id'=>NULL, 'text'=>'Second Parent'),
array('id'=>5, 'parent_id'=>4, 'text'=>'Second Child')
);
This will return a multidimensional array. If one item has no children, $comment['children']
will equal NULL
, otherwise the respective array of children will be attached.
function arrangecomments($comments){
$tree = array();
/* We get all the parent into the tree array */
foreach ($comments as &$node) {
/* Note: I've used 0 for top level parent, you can change this to == 'NULL' */
if($node['parent_id']=='0'){
$tree[] = $node;
unset($node);
}
}
/* This is the recursive function that does the magic */
/* $k is the position in the array */
function findchildren(&$parent, &$comments, $k=0){
if (isset($comments[$k])){
if($comments[$k]['parent_id']==$parent['id']){
$com = $comments[$k];
findchildren($com, $comments); // We try to find children's children
$parent['children'][] = $com;
}
findchildren($parent, $comments, $k+1); // And move to the next sibling
}
}
/* looping through the parent array, we try to find the children */
foreach ($tree as &$parent) {
findchildren($parent, $comments);
}
return $tree;
}
I know it can be improved a lot, but it works, and I haven't found any bugs so far. Hope it helps!
Upvotes: 0
Reputation: 157839
BTW, in case of using Materialized Path technique, you won't need no recursion nor nested array or stuff.
Just plain linear outpur from the database.
To do that just create a field named path
in your database and fill it with all the parent id's, padded to some considerabe length.
Say, example tree may look like
id 1 root path
id 3 root 1 path 000000001
id 5 root 1 path 000000001000000003
id 4 root 1 path 000000001
id 2 root path 000000002
id 6 root 2 path
so, querying your table by simple ORDER BY root DESC, path ASC
you will get your tree as a simple already ordered list
Upvotes: 2