How can using php mysql create a dynamic tree for this tables
tbl_folder
db_id db_foldername
1 accounting
2 hr
3 it
tbl_subfolder
db_id db_folderid db_subfoldername
1 1 xxx
2 1 yyy
3 2 zzz
tbl_childsubfolder
db_id db_subfolderid db_childsubfoldername
1 1 ffff
2 2 llll
tbl_subchild
db_id db_childsubfolderid db_subchildname
1 1 eee
2 1 ppp
accounting
xxx
fff
eee
ppp
yyy
lll
hr
zzz
it
include("include/connect.php");
--SELECT--
$name";
}
?>
if(isset($_POST['add'])){
$foldername=$_POST['txt_name'];
$select=$_POST['txt_select'];echo $select;
$explod=explode("-",$select);
$path=$explod['0'].';'.$explod['1'];
if($path==";"){$path="";}
$parent_id=$explod['1'];
if($foldername==""){echo"enter a name";}
else{
$insert_query=mysqli_query($conn,"insert into tbl_folders(parent_id,path,name)values('$parent_id','$path','$foldername')")or die(mysqli_error($conn));
header("location:index.php");
}
}
$sql=mysqli_query($conn,"select * from tbl_folders where parent_id='0'")or die(mysqli_error($conn));
while($row=mysqli_fetch_array($sql)){
$name=$row['name'];
$id=$row['db_id'];
echo $name;echo"<br/>";
$sqli=mysqli_query($conn,"select * from tbl_folders where parent_id='$id'")or die(mysqli_error($conn));
while($row=mysqli_fetch_array($sqli)){
$name=$row['name'];
$id=$row['db_id'];
$path=$row['path'];
$x=explode(";",$path);echo $path;echo"<br/>";
$pa=$x['1'];
echo $name;echo"<br/>";
$sqli=mysqli_query($conn,"select * from tbl_folders where parent_id='$id' and path='$pa'")or die(mysqli_error($conn));
while($row=mysqli_fetch_array($sqli)){
$name=$row['name'];
$id=$row['db_id'];
$path=$row['db_path'];
echo $name;echo"<br/>";}
}
}
Building the tree
You can build one table with the following fields:
`id (int), parent_id (int), path (vachar), name`
id - is the identifier
parent_id - refers to the id of the parent in the same table
path - is the path of parent ids to the given element
Example entries in the table:
|id | parent_id | path | name|
-------------------------------
|1 | 0 | | A |
-------------------------------
|2 | 1 |;1; | B |
-------------------------------
|3 | 2 |;1;2; | C |
where A is the parent, B is child of A, and C is child of B.
In your backend logic you need to have the following:
When you add/edit new item in this table - if it is root parent (with no parents above it) you insert it with parent_id=0 and path=''
When you add/edit new item in this table - if it has parent then you insert it with parent_id=:idOfParent and path=CONCAT(:parentPath, ';', :idOfParent, ';')
where :idOfParent - is the parent id value and :parentPath is the path of the parent which you concatenate with the ;:idOfParent;
; - is the separator for the ids in the path
Path column gives you the advantage of directly getting all the parents of given element without using recursive approaches.
So if you select an item with path ';1;2;3;' and you need the info for the parents also you will have 1 + 3 SELECT queries in total.
And when deleting an item you can do this:
DELETE FROM table WHERE path LIKE (';:deleteId;')
where :deletedId is the id of the deleted element. This query will delete all the entries that have deleted item as a parent.
Visualization of the tree
you can get the $data with this query
'SELECT id, parent_id, path, name FROM table WHERE 1;'
But for the test i use the following example array
$data = [
0 => ['id' => 1, 'parent_id' => 0, 'path' => '', 'name' => 'A'],
1 => ['id' => 2, 'parent_id' => 1, 'path' => ';1;', 'name' => 'B'],
2 => ['id' => 3, 'parent_id' => 2, 'path' => ';1;2;', 'name' => 'C'],
3 => ['id' => 4, 'parent_id' => 3, 'path' => ';1;2;3;', 'name' => 'D'],
4 => ['id' => 5, 'parent_id' => 1, 'path' => ';1;', 'name' => 'E'],
5 => ['id' => 6, 'parent_id' => 2, 'path' => ';1;2;', 'name' => 'G'],
6 => ['id' => 7, 'parent_id' => 0, 'path' => '', 'name' => 'H'],
];
$ref = null;
$tree = [];
foreach($data as $item) {
if($item['path']) {
$path = ltrim($item['path'], ';');
$path = rtrim($path, ';');
$pathArray = explode(';', $path);
$i = 0;
foreach($pathArray as $parentId) {
if($i === 0) {
if(!isset($tree[$parentId])) {$tree[$parentId] = ['name' => [], 'children' => []];}
$ref = &$tree[$parentId]['children'];
}
else {
if(!isset($ref[$parentId])) $ref[$parentId] = ['name' => [], 'children' => []];
$ref = &$ref[$parentId]['children'];
}
$i++;
}
if($ref !== null) {
$ref[$item['id']]['name'] = $item['name'];
$ref[$item['id']]['children'] = [];
}
}
else {
$tree[$item['id']]['name'] = $item['name'];
$tree[$item['id']]['children'] = [];
}
}
Output part:
print '<pre>';
print_r($tree);
print '</pre>';
So here you change the code according to your needs. Print it in the way you want (may be you will need recurrsion to access every tree node)
Related
i made a navigation where a MySQL Database is needed.
This is my connection to the database to get all informations.
$stmt = $pdo->prepare("SELECT * FROM navigation");
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_OBJ);
if($stmt->rowCount() > 0){
$primary_nav = [];
foreach ($results as $result){
if($result->sub == 0){
$primary_nav[] = array(
'name' => $result->name,
'url' => $result->url,
'icon' => $result->icon,
);
}elseif($result->sub == 1){
$primary_nav[] = array(
'name' => $result->name,
'icon' => $result->icon,
'sub' => array(
array(
'name' => $result->name_sub,
'url' => $result->url_sub
)
)
);
}
}
}
This works fine, if I add the navigation into the database everything looks perfect and works amazing.
Now the problem i've now is when I want to a new sub menu than everytime I get a new top menu entrie with just 1 sub menu.
So my question is, how do I get this part working without breaking the code.
Normally the code looks like this:
// first sub
array(
'name' => 'Test1',
'icon' => 'fa fa-bullhorn',
'sub' => array(
array(
'name' => 'First Sub 1',
'url' => 'sub1.php'
),
array(
'name' => 'First Sub 2',
'url' => 'sub2.php'
)
)
),
// second sub
array(
'name' => 'Test3',
'icon' => 'fa fa-bullhorn',
'sub' => array(
array(
'name' => 'Second Sub',
'url' => 'sub1_1.php'
)
)
)
database structure:
|-----name-----|----url----|----icon----|----sub----|----name_sub----|----url_sub----|----category----|
| Dashboard | index.php | icon | 0 | | | |
------------------------------------------------------------------------------------------------------
| Test | test.php | icon | 0 | | | |
------------------------------------------------------------------------------------------------------
| Test1 | | icon | 1 | First Sub 1 | sub1.php | 1 |
------------------------------------------------------------------------------------------------------
| | | icon | 1 | First Sub 2 | sub2.php | 1 |
------------------------------------------------------------------------------------------------------
| Test3 | | icon | 1 | Second Sub | sub1_1.php | 2 |
------------------------------------------------------------------------------------------------------**
So if the category equals the same number as the other it should be doing this:
Test1
-- First Sub 1
-- First Sub 2
Test3
-- Second Sub
but with my code it looks like this:
Test1
-- First Sub 1
Test2 (it would be empty because in the database it is empty just for example I puted Test2)
-- First Sub 2
Test3
-- Second Sub
maybe someone understand what I need, because my english is not the best to explain it. Thanks for any help/solution for this problem.
$stmt = $pdo->prepare("SELECT * FROM navigation");
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_OBJ);
if($stmt->rowCount() > 0){
$categories = [];
$primary_nav = [];
foreach ($results as $result){
if ($result->name) {
if ($result->category) {
$categories[$result->category] = sizeof($primary_nav);
}
$primary_nav[] = array(
'name' => $result->name,
'url' => $result->url,
'icon' => $result->icon,
);
}
if ($result->name_sub) {
$primary_nav[$categories[$result->category]]['sub'][] = array(
'name' => $result->name_sub,
'url' => $result->url_sub
);
}
}
}
I've added an extra $categories array.
For each "parent" entry with a category, the $categories array stores the category value from the database and the key of the "parent" entry in the $primary_nav array.
The $categories array can then be used to add subsequent subcategories to the correct parent entry using their category value.
In your current setup however, the database allows you to have subcategories without a parent category and (sub)categories without a name.
So I would suggest using a table setup like this instead:
id name url icon parent
1 Dashboard index.php icon null
2 Test test.php icon null
3 Test1 null icon null
4 First sub 1 sub1.php null 3
5 First sub 2 sub2.php null 3
6 Test3 null icon null
7 Second sub Sub1_1.php null 6
Parent categories have the column "parent" set to null, and subcategories have their "parent" column set to the id of their parent entry.
This also allows you to have sub-sub-(and so on)-categories.
You would need to query it recursively:
function buildNav($pdo, $id = null) {
$array = [];
if ($id) {
$stmt = $pdo->prepare("SELECT * FROM navigation WHERE parent = :id");
$stmt->bindValue('id', $id);
} else {
$stmt = $pdo->prepare("SELECT * FROM navigation WHERE parent IS NULL");
}
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_OBJ);
if ($stmt->rowCount() > 0){
foreach ($results as $result){
$array[] = array(
'name' => $result->name,
'url' => $result->url,
'icon' => $result->icon,
'sub' => buildNav($pdo, $result->id)
);
}
}
return $array;
}
$primary_nav = buildNav($pdo);
I'm trying to get the content I need from a joined query and properly use values as an array key so that I can build some DIV lists properly
My php query and array:
$getTickers = "
SELECT d.ID as displayID, d.display_name as display, l.location_name as locationName, d.location_id as location, t.id as ticker, tc.id as contentID, tc.content
FROM displays d
INNER JOIN locations l on d.location_id = l.id
INNER JOIN tickers t on d.id = t.display_id
INNER JOIN ticker_content tc on t.id = tc.ticker_id;
";
$tickers = $mysqlConn->query($getTickers);
$tickerDisplays = array();
foreach($tickers as $subArray) {
if(!array_key_exists($subArray['displayID'], $tickerDisplays)) {
$tickerDisplays[$subArray['displayID']] = array();
}
// here you add `display_name` under key `display_id`
$tickerDisplays[$subArray['displayID']][$subArray['location']] = $subArray['display'];
}
All examples and code below, but I don't need the html structure help with this, just how to restructure the array/key to give me the desired results and how I should loop them on the front end.
I'm getting 4 divs as I expect right now (one for each unique display/location)
but I need to figure out how to correcty arrange it so I can echo the DIsplay name as the h4, the location as h5, and then each content in my list
So the query result gives me this:
displayID | display | locationName | location | ticker | contentID | content |
1 Office Building 4 4 1 1 testing content
2 Lobby Building 4 4 2 2 testing content 2
3 Lobby Building 1 1 3 3 testing content 3
4 Office Building 1 1 4 4 testing content 4
4 Office Building 1 1 4 5 testing content again
I'm trying to loop on this with the expected result of having a a div for each location/display combo like so:
OFFICE
Building 4
testing content
---------------
LOBBY
Building 4
testing content 2
------------------
LOBBY
Building 1
testing content 3
------------------
OFFICE
Building 1
testing content 4
testing content again
----------------------
Here's the way I'm currently trying to loop that
<?php foreach($tickerDisplays as $key => $ticker):?>
<h4><?php echo $key ?></h4> //so this should be the display Name (office, lobby)
<h5><?php echo //location?></h5> //this should be the location name (Building 1, Building 4)
//This will be another foreach for any content associated with the location/display
<ul class="tickerContent">
<li>
</ul>
</div>
</div>
<?php endforeach;?>
The approach here is to make a child array for each display line to contain all
the multiple content records.
// Dummy the data from the query
$tickers = [
['displayID' => 1, 'display' => 'Office', 'locationName' => 'Building 4', 'location' => 4, 'ticker' => 1, 'contentID' => 1, 'content' => 'testing content'],
['displayID' => 2, 'display' => 'Lobby', 'locationName' => 'Building 4', 'location' => 4, 'ticker' => 2, 'contentID' => 2, 'content' => 'testing content 2'],
['displayID' => 3, 'display' => 'Lobby', 'locationName' => 'Building 1', 'location' => 1, 'ticker' => 3, 'contentID' => 3, 'content' => 'testing content 3'],
['displayID' => 4, 'display' => 'Office', 'locationName' => 'Building 1', 'location' => 1, 'ticker' => 4, 'contentID' => 4, 'content' => 'testing content 4'],
['displayID' => 4, 'display' => 'Office', 'locationName' => 'Building 1', 'location' => 1, 'ticker' => 4, 'contentID' => 5, 'content' => 'testing content again']
];
// A place to keep the reorganized data
$tickerDisplays = [];
// Walk through the query result
foreach($tickers as $row) {
$displayID = $row['displayID']; // for convenience and readability
$location = $row['location']; // for convenience and readability
$display = $row['display'];
$contentID = $row['contentID'];
if ( ! array_key_exists($row['displayID'], $tickerDisplays) ) {
$tickerDisplays[$displayID] = [
'displayID' => $row['displayID'],
'display' => $row['display'],
'ticker' => $row['ticker'],
'contentID' => $row['contentID'],
'content' => $row['content'],
'location' => $row['location'],
'locationName' => $row['locationName'],
'#content' => [] // to store the content data
];
}
$tickerDisplays[$displayID]['#content'][$contentID] = ['content' => $row['content']];
}
print_r($tickerDisplays);
foreach ( $tickerDisplays as $key => $ticker ) {
// Output the display and location name
out($ticker['display']);
out($ticker['locationName']);
// Output all the content records.
foreach ( $ticker['#content'] as $contentID => $content ) {
out($content['content']);
}
out('------------');
}
// Just a utility function
function out($msg) {
echo "$msg\n";
}
Output:
Office
Building 4
testing content
------------
Lobby
Building 4
testing content 2
------------
Lobby
Building 1
testing content 3
------------
Office
Building 1
testing content 4
testing content again
------------
I have 2 tables. The first one contain some global information, and the second contain a list of images.
When I execute this request:
SELECT table1.title, table1.description, table2.image LEFT JOIN table2 ON table2.table1_id = table1.table1_id
Tables structure:
TABLE1
| table1_id | title | description |
| 1 | title1 | description1 |
| 2 | title2 | description2 |
| 3 | title3 | description3 |
TABLE2
| id | table1_id | image |
| 1 | 1 | img/img1.png |
| 2 | 1 | img/img2.png |
| 3 | 1 | img/img3.png |
| 4 | 2 | img/img4.png |
| 5 | 2 | img/img5.png |
| 6 | 3 | img/img6.png |
I got something like that:
<?php
array(
array('title' => 'title1', 'description' => 'description1', 'image' => 'img/img1.png'),
array('title' => 'title1', 'description' => 'description1', 'image' => 'img/img2.png'),
array('title' => 'title1', 'description' => 'description1', 'image' => 'img/img3.png'),
array('title' => 'title2', 'description' => 'description2', 'image' => 'img/img4.png'),
array('title' => 'title2', 'description' => 'description2', 'image' => 'img/img5.png'),
array('title' => 'title3', 'description' => 'description3', 'image' => 'img/img6.png')
);
?>
The problem with this kind of structure is duplicated title, description.
I'd like to get something like that:
<?php
array(
array('title' => 'title1', 'description' => 'description1', 'image' =>
array('img/img1.png', 'img/img2.png', 'img/img3.png')
),
array('title' => 'title2', 'description' => 'description2', 'image' =>
array('img/img1.png', 'img/img2.png')
),
array('title' => 'title3', 'description' => 'description3', 'image' =>
array('img/img6.png')
)
);
?>
My questions are:
Is it possible to get this kind of structure of data just with a SQL request (No PHP manipulation..)
If not, what kind of PHP manipulation I have to do to transform my first array to my second array?
Thanks!
Have a look at group clause and group_concat function. I'm not sure whether it creates an array in PHP, but it's almost what you want:
SELECT table1.title, table1.description, GROUP_CONCAT(table2.image) LEFT JOIN table2 ON table2.id = table1.id GROUP BY table1.id
You can use explode function in PHP to transform the result of GROUP_CONCAT(table2.image) to PHP array
See the documentation of MySQL's group_concat and PHP's explode functions.
You can do a select on all the distinct (Name, Description) tuples. Then you'll have an array of Name,Descriptions, and a null third element. Then loop through this array and get all the images for that distinct tuple. Then take that result and insert it into the third element.
Query get array of name/descriptions:
select distinct table1.title, table2.description left join table2 on table2.id = table1.id
Query to find all images of the distinct name/description tuples:
select table2.image inner join table1 on table1.id = table2.id where table1.name = arr[0] and table1.description = arr[1]
You can quite easily build the structure you're after when you iterate over the results, either was you're going to have to manipulate the result-set.
<?php
$items = array();
foreach ($rows as $row) {
if ( ! isset($items[ $row['title'] ])) {
$items[ $row['title'] ] = array(
'title' => $row['title'],
'description' => $row['description'],
'images' => array($row['image']),
);
continue;
}
$items[ $row['title'] ]['images'][] = $row['image'];
}
$items = array_values($items);
Anthony.
PHP code:
<?php
/*here is your result array*/
$result = array(
array('title' => 'tile1', 'description' => 'description1', 'image' => 'img/img1.png'),
array('title' => 'tile1', 'description' => 'description1', 'image' => 'img/img2.png'),
array('title' => 'tile1', 'description' => 'description1', 'image' => 'img/img3.png'),
array('title' => 'tile2', 'description' => 'description2', 'image' => 'img/img4.png'),
array('title' => 'tile2', 'description' => 'description2', 'image' => 'img/img5.png'),
array('title' => 'tile3', 'description' => 'description3', 'image' => 'img/img6.png')
);
/*creating a new formatted array*/
$newResult = array();
foreach($result as $value){
$newResult[$value['title']]['title'] = $value['title'];
$newResult[$value['title']]['description'] = $value['description'];
$newResult[$value['title']]['image'][] = $value['image'];
}
/*printing new final formatted array*/
print_r($newResult));
?>
I want a table of comments like so
id | comment | parent_id
--------------------------
1 text1 0
2 text2 1
3 text3 2
4 text4 3
5 text5 3
6 text6 5
I want to construct an array displaying the hierarchy of the parents and children. The tree should go back a undetermined number of generations. I don't want to use nesting foreach loops as I'm not sure how deep it goes. That is why I'm here, I'm not sure of the best practice for a problem like this. I also want to display the depth in the array. Below is an example. It doesn't really relate to table above, but hopefully gives you an idea of what I need.
array(
"depth"=> 4
"parent" => array(
"id"=> 1,
"comment" => "sometext1"
"child_count" => 2,
"children" => array(
0 => array(
"id" => 2
"comment" => "sometext2",
"child_count" => 0,
"children" => null
),
1 => array(
"id" => 3
"comment" => "sometext3"
"child_count" => 1,
"children" => array(
0 => array(
"id" => 2
"comment" => "sometext2",
"child_count" => 2,
"children" => array(
0 => array(
"id" => 2
"comment" => "sometext2",
"child_count" => 0,
"children" => null
),
1 => array(
"id" => 2
"comment" => "sometext2",
"child_count" => 1,
"children" => array(
"id" => 2
"comment" => "sometext2",
"child_count" => 0,
"children" => null
)
)
)
)
)
)
)
)
I was going to use foreach and do a SQL statement to retrive that parent/childs children. ie
$sql = "SELECT * FROM comments WHERE parent = $parent_id";
Im not really looking for the code for all this, just a pseudo code solution.
This can be easily done in PHP... For this you need two arrays and a two while loops.
This code will make a tree the way you wanted and for an undetermined depth and number of children.
Pastebin to the working code.
Using references, lets imagine everything is saved in an array $data with this structure: (id, comment, parent_id) where parent_id points to an id.
Code to build the tree.
$tree = array();
reset($data);
while (list($k, $v) = each($data))
if (0 == ($pid = $v['parent_id']))
$tree[$k] =& $data[$k]; else
$data[$pid]['children'][$k] =& $data[$k];
And to generate the depth and child count.
reset($data);
while (list($k, $v) = each($data))
if (0 != $v['parent_id'])
{
$ref =& $data[$k];
$depth = 0;
do
{
if ($depth) $ref =& $data[$ref['parent_id']];
$dre =& $ref['depth'];
if (!isset($dre) || $dre <= $depth) $dre = $depth++;
if (isset($ref['children']))
$ref['child_count'] = count($ref['children']);
else
{
$ref['child_count'] = 0;
$ref['children'] = null;
}
}
while ($ref['parent_id']);
}
All my code has been written on the fly and not even tested, so if there are any errors please forgive meeeeeeeee!!!!!!!!!!! ← Forget that, I tried it, fixed a couple of issues and now works perfectly.
Note
For this code to work, the index of every item has to be equal to its ID.
The array I used to try the code.
$data = array(
'1' => array('id' => '1', 'comment' => 'a', 'parent_id' => 0),
'2' => array('id' => '2', 'comment' => 'b', 'parent_id' => 0),
'3' => array('id' => '3', 'comment' => 'c', 'parent_id' => 1),
'4' => array('id' => '4', 'comment' => 'd', 'parent_id' => 1),
'5' => array('id' => '5', 'comment' => 'e', 'parent_id' => 2),
'6' => array('id' => '6', 'comment' => 'f', 'parent_id' => 2),
'7' => array('id' => '7', 'comment' => 'g', 'parent_id' => 5),
'8' => array('id' => '8', 'comment' => 'h', 'parent_id' => 7)
);
This is the problem when you use Adjacency list for trying to retrieve all child nodes in the hierarchy. It just doesn'y handle recursion very well if you are using mysql. (Oracle is another matter).
Creating the structure is simple, you should not really concern yourself with how to create the array structure just yet, first you want to try and create an efficient query and effiecient models that play perfectly to the type of queries that you will be making.
For example, you say that you want to retrieve all child nodes. Well then you should probably be using nested set models instead or in addition to adjacency list.
Take a look at some of these resources...
Is there a simple way to query the children of a node?
The idea of a nested set, is that you store the lft and right edge values of a node, meaning that retrieving any child nodes, is incredibly simple, beause you just select nodes which have a lft value greater than the target nodes lft value, and smaller than the rgt value.
Once you retrieve your result set, creating your array structure will be effortless.
See here : http://en.wikipedia.org/wiki/Nested_set_model
Once you have your results, then take a look at this question, which I asked a year or so ago, which is exactly what you want. PHP > Form a multi-dimensional array from a nested set model flat array
Example
id | comment | parent_id | lft | rgt |
-------------------------------------------------
1 World null 1 12
2 Europe 1 2 11
3 England 2 3 10
4 Kent 3 4 5
5 Devon 3 6 9
6 Plymouth 5 7 8
Hey guys I'm trying to learn codeigniter, but once again I'm STUCK and I seek help (as usual :P )
What I need to do?
-> I need to get the data related to a article from the database along with other stuff like the tags for the article and all the comments. I'm thinking of keeping single level nested comments for the article.
Well I'm done with the tag part [link to the answer which helped me with the same : Returning and using multidimensional array of records from database in CodeIgniter 2.0 ] but the comment part is driving me nuts.
Well to get started here is my comments table
Comments
+---------------+-------------+
| Field | Type |
+---------------+-------------+
| commentId | int(10) |
| PostId | int(10) |
| author | varchar(30) |
| email | varchar(30) |
| url | varchar(50) |
| date | datetime |
| comment | text |
| parent | int(10) |
+---------------+-------------+
I'm using the parent field to keep a track of the parent for a nested child comment. By default the value is 0 which means it the parent. Child comment will have the commentid of its parent comment
public function getPost($postName = NULL , $year = NULL, $month = NULL ){
if($postName != NULL && $year != NULL && $month != NULL){
//single post
$this->load->model('comment_model');
$this->db->where('postName',$postName);
$this->db->where('year(date)',$year);
$this->db->where('month(date)',$month);
$q = $this->db->get('mstack_Post');
if($q->num_rows()>0){
$post = $q->result();
foreach ($post as &$p) {
$p->tags = $this->getAllTags($p->postId);
/* getting the comments */
$com = $this->comment_model->getComments($p->postId);
/*echo count($com).' is the total count'; output= 4 */
foreach ($com as &$c) {
/* trying to filter the comment. but all I get is 1 comment as the output*/
if($c->parent==0){
$p->comments->parentComment = $c;
}elseif($c->commentId==$c->parent){
$p->comments->childComment = $c;
}
}
}
return $post;
}else{
return array();
}
}
}
Any help will surely be appreciated.
If you have any other technique /idea to display multi level comments then do let me know. :)
Here is the solution that might be helpfull:
First you need 2 helper recursive function:
// Building comments.
function buildComments($list, $parent = 0)
{
// Creating result array.
$result = array();
//looping...
foreach ($list as $item)
{
//iteration starts with 0 as default.
if ($item->parent == $parent)
{
// add to the result
$result[$item->commentId] = array(
'author' => $item->author,
// ... other definitions
'child' => buildComments($list, $item->commentId) //execute this function for child.
);
}
}
return $result;
}
function printComments($arg, $depth = 1)
{
foreach ($arg as $item)
{
// Printing comment...
echo str_repeat(' ', $depth) . $item['author'] . "<br />\r\n";
// extra echoes...
// if it has a child comment...
if (count($item['child'] > 0))
{
printComments($item['child'], $depth + 1);
}
}
}
A little explaining:
The buildComments() function will starts with rows that parents has 0. Then it will execute itself for child. if child as a child, it will add it. In the end, result will be like this:
$result = array(
1 => array(
'author' => 'John',
'child' => array(
8 => array(
'author' => 'Jane',
'child' => array(
3 => array(
'author' => 'Jamie',
'child => array()
)
)
),
6 => array(
'author' => 'Jackie',
'child => array()
),
9 => array(
'author' => 'Harry',
'child => array()
)
)
),
4 => array(
'author' => 'Jack',
'child' => array()
),
10 => array(
'author' => 'Clark',
'child' => array(
11 => array(
'author => 'Lois',
'child' => array()
)
)
),
12 => array(
'author' => 'Luthor',
'child' => array()
)
);
In the printComments() function we are printing results recursive. for each child, function repeats itself. You will get result like this:
John
Jane
Jamie
Jackie
Harry
Jack
Clark
Lois
Luthor
For more information about recursive functions Look this answer
USAGE
$this->db->where('postName',$postName);
$this->db->where('year(date)',$year);
$this->db->where('month(date)',$month);
$this->db->order_by('parent', 'asc');
$query = $this->db->get('comments');
$comments = buildComments($query->result());
printComments($comments);
that'is that simple...