I'm still new with PHP & MySQL. This quetion looks simple, but somehow I can't figure the recursive formulae to create tree-like hierarchy by using foreach and array correctly.
This is the table structure
CREATE TABLE IF NOT EXISTS `table` (
`id` int(2) NOT NULL,
`lecturer` varchar(50) NOT NULL,
`subject` varchar(9) NOT NULL,
`section` int(2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
INSERT INTO `table` (`id`, `lecturer`, `subject`, `section`) VALUES
(1, 'Prof A', 'info2222', 1),
(2, 'Prof A', 'info2222', 2),
(3, 'Prof A', 'info3333', 1),
(4, 'Prof A', 'info3333', 3),
(5, 'Prof B', 'info4444', 1);
This is sample output that I want:
=================================================
| lecturer > subject > section | count total |
=================================================
| Prof A | 4 |
| |---info2222 | 2 |
| | |---1 | 1 |
| | |---2 | 1 |
| | | |
| |---info3333 | 2 |
| |---1 | 1 |
| |---3 | 1 |
| | |
| Prof B | 1 |
| |---info4444 | 1 |
| |---1 | 1 |
=================================================
my full code (currently)
<html>
<head>
<?php
mysql_select_db('testing',mysql_connect('localhost','root',''))or die(mysql_error());
function count_recursive($array)
{
$c = 0;
foreach($array as $value)
{
if(is_array($value))
$c += count_recursive($value);
else
$c++;
return $c;
}
}
?>
</head>
<body>
<?php
$query = $pdo->query("Select * from table");
$arr = [];
while($data = $query->fetch())
{
$arr[$data['lecturer']][$data['subject']][] = $data['section'];
}
foreach($arr as $lecturer => $lvalues)
{
echo $query['lecturer'] ;
foreach($lvalues as $subject => $svalues)
{
echo $query['subject'] ;
foreach($svalues as $section)
{
echo $query['section'] ;
}
}
}
?>
</body>
</html>
Something like this should work:
$query = $pdo->query("Your select...");
$arr = [];
while($data = $query->fetch()){
$arr[$data['lecturer']][$data['subject']][] = $data['section'];
}
Afterwards you can foreach over the (3d) array:
foreach($arr as $lecturer => $lvalues){
//echo your lecturer here
foreach($lvalues as $subject => $svalues){
//echo your subject here
foreach($svalues as $section)
//echo sour section here
}
to count everything recursively you can use:
function count_recursive($array){
$c = 0;
foreach($array as $value)
if(is_array($value))
$c += count_recursive($value);
else
$c++;
return $c;
}
Related
I have a mysql table id, gra, grb integers and NOT NULLS and contain DIFFERENT numbers between 1 and 10.
I'd like to divide the data from gra and grb to different columns according to their value.
example: mysql table:
+------------+------------+------------+
| id | gra | grb |
+------------+------------+------------+
| 1 | 2 | 6 |
+------------+------------+------------+
| 2 | 10 | 8 |
+------------+------------+------------+
| 3 | 9 | 5 |
+------------+------------+------------+
etc
The expected table output would be like this:
+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
| gr1 | gr2 | gr3 | gr4 | gr5 |gr6 | gr7 |gr8 |gr9 |gr10 |
+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
| | 2 | | | | 6 | | | | |
+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
| | | | | | | | 8 | | 10 |
+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
| | | | | 5 | | | | 9 | |
+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
Is there an easy way to do this? I figured I could do this using mysql with CASE function but it'd be too long. I think there should be an easier way. Can I get help with this, please? thanks.
You can get the desired result using this approach
// Create connection
$conn = new mysqli('hostname', 'username', 'password', 'dbname');
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT gra ,grb FROM `tablename`";
$result = $conn->query($sql);
$rows = array();
$i = 0;
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
foreach(range(1,10) as $key => $value){
$_key = 'gr'.$value;
$rows[$i][$_key] = ($row['gra'] == $value) ? $row['gra'] : ( ($row['grb'] == $value) ? $row['grb'] : null);
}
$i++;
}
}
echo '<pre>';
print_r($rows);
You can print in a table like this
$sql = "SELECT gra ,grb FROM `grade`";
$result = $conn->query($sql);
$rows = array();
$i = 0;
$html = '<table border="1"><tr>';
foreach(range(1,10) as $v){
$html.= '<td>gr'.$v.'</td>';
}
$html .= '</tr>';
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$html .= '<tr>';
foreach(range(1,10) as $key => $value){
$_key = 'gr'.$value;
$rows[$i][$_key] = ($row['gra'] == $value) ? $row['gra'] : ( ($row['grb'] == $value) ? $row['grb'] : null);
$html .= '<td> '.$rows[$i][$_key].' </td>';
}
$html .= '</tr>';
print_r($rows[$i]);echo '<hr>';
$i++;
}
}
$html .= '</table>';
echo $html;
I am trying to create table with usernames and data assigned to each username.
I have projects and inside each project there are several processes. So want I want to to is to print table with usernames and projects displayed, and then assign each process to the username. Something like this:
username| project TMNT | project LEON | project MAT |
--------+--------------------+----------------+---------------+
barikan | ANM BLD, BGD CUP | N/A | N/A |
beny | N/A | N/A | BGD CUP |
bob | N/A | ANM BLD | N/A |
Where ANM BLD, BGD CUP are the processes from each project.
What I am able to do is to print projects as headers horizontally and usernames vertically:
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<?php
$result = getRecord();
$count = 0;
if (mysqli_num_rows($result) > 0)
while($row = mysqli_fetch_array($result))
{
$projectNo = $row['projectNo'];
$title = $row['title'];
$code = $row['code'];
echo "<th>".$projectNo." ".$title." ".$code."</th>";
$count++;
}
?>
</tr>
</thead>
<tbody>
<?php
$result3 = getLeader();
if (mysqli_num_rows($result3) > 0)
while($row = mysqli_fetch_array($result3))
{
$username = $row['username'];
echo "<tr>
<td>".$username."</td>";
}
?>
</tbody>
And how my database tables look like:
user table
uid| username| salary|
---+---------+-------+
1 | bob | 0 |
2 | barikan | 0 |
3 | beny | 0 |
4 | adam | 0 |
project table
projectNo| title|
---------+------+
1610004 | TMNT |
1610005 | LEON |
1610006 | MAT |
process table(where person is assigned to a process)
projectNo| process | proc_leader|
---------+---------+------------+
1610004 | ANM BLD | barikan |
1610004 | BGD CUP | barikan |
1610005 | ANM BLD | bob |
1610006 | BGD CUP | beny |
I know i can use group_concat function to concat all processes in for same project in one row but how can i print accordingly to each project?
Sql query i am using to concat processes:
"SELECT proc_leader.projectNo, group_concat(proc_leader.process) AS processes, username
FROM user
LEFT OUTER JOIN proc_leader ON user.username=proc_leader.proc_leader
GROUP BY username, proc_leader.projectNo";
EDIT
so what if I have two tables:
process table(where person is assigned to a process)
projectNo| process | proc_leader|
---------+---------+------------+
1610004 | ANM BLD | barikan |
1610004 | BGD CUP | barikan |
1610005 | ANM BLD | bob |
1610006 | BGD CUP | beny |
proc_checker table(where person is assigned to a process in different role)
projectNo| process | proc_checker|
---------+---------+-------------+
1610004 | ANM BLD | adam |
1610004 | BGD CUP | barikan |
1610005 | ANM BLD | barikan |
1610006 | BGD CUP | beny |
So in the final result it should be smth like this(leaders, checkers together):
username| project TMNT | project LEON | project MAT |
--------+------------------------------------------+----------------+---------------------------------+
adam | ANM BLD(chk) | N/A | N/A | |
barikan | ANM BLD(ld), BGD CUP(ld), BGD CUP(chk) | ANM BLD(chk) | N/A |
beny | N/A | N/A | BGD CUP(ld), BGD CUP(chk) |
bob | N/A | ANM BLD(ld) | N/A |
Where ld= leader;
chk=checker
Should I LEFT JOIN both tables? Thanks for help
Assume you have table structure like this (sqlfiddle):
CREATE TABLE `user` (
`uid` INT(11) UNSIGNED NOT NULL PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
salary INT(11) UNSIGNED NOT NULL DEFAULT 0
);
CREATE TABLE project (
projectNo INT(11) UNSIGNED NOT NULL PRIMARY KEY,
title VARCHAR(255) NOT NULL UNIQUE
);
CREATE TABLE process (
projectNo INT(11) UNSIGNED NOT NULL,
process VARCHAR(255) NOT NULL,
proc_leader VARCHAR(255) NOT NULL,
FOREIGN KEY(projectNo) REFERENCES project(projectNo),
FOREIGN KEY(proc_leader) REFERENCES `user`(username)
);
CREATE TABLE proc_checker (
projectNo INT(11) UNSIGNED NOT NULL,
process VARCHAR(255) NOT NULL,
proc_checker VARCHAR(255) NOT NULL,
FOREIGN KEY(projectNo) REFERENCES project(projectNo),
FOREIGN KEY(proc_checker) REFERENCES `user`(username)
);
INSERT INTO `user`(uid, username, salary)
VALUES
(1, "bob", 0),
(2, "barikan", 0),
(3, "beny", 0),
(4, "adam", 0);
INSERT INTO project(projectNo, title)
VALUES
(1610004, "TMNT"),
(1610005, "LEON"),
(1610006, "MAT");
INSERT INTO process(projectNo, process, proc_leader)
VALUES
(1610004, "ANM BLD", "barikan"),
(1610004, "BGD CUP", "barikan"),
(1610005, "ANM BLD", "bob"),
(1610006, "BGD CUP", "beny");
INSERT INTO proc_checker(projectNo, process, proc_checker)
VALUES
(1610004, "ANM BLD", "adam"),
(1610004, "BGD CUP", "barikan"),
(1610005, "ANM BLD", "barikan"),
(1610006, "BGD CUP", "beny");
Result snippet with some commets is below:
<?php
// root root :)
$conn = mysqli_connect('127.0.0.1', 'root', 'root', 'test3');
// 1.Get data
// data for final table
// format is [username][projectNo] => [process1, process2, ..., processN]
$result = [];
// map project no to its title
$projectNoToTitle = [];
$sql = '
SELECT uid, username
FROM `user`
ORDER BY username
';
$query = mysqli_query($conn, $sql);
// for each user
while ($data = mysqli_fetch_assoc($query)) {
$sql = '
SELECT a.* FROM
(
(
-- select pairs project - leader
SELECT p.projectNo, p.title, CONCAT(pr.process, "(ld)") AS process
FROM project p
LEFT JOIN process pr ON p.projectNo = pr.projectNo
AND pr.proc_leader = "' . mysqli_real_escape_string($conn, $data['username']) . '"
)
-- union all means we union result of queries, which have structure
-- and don\'t remove duplicates (it\'s faster than UNION and
-- more logical because in our sittuation it won\'t be any duplicates)
UNION ALL
(
-- select pairs project - checker
SELECT p.projectNo, p.title, CONCAT(pch.process, "(chk)") AS process
FROM project p
LEFT JOIN proc_checker pch ON p.projectNo = pch.projectNo
AND pch.proc_checker = "' . mysqli_real_escape_string($conn, $data['username']) . '"
)
) AS a
ORDER BY a.projectNo
';
$query2 = mysqli_query($conn, $sql);
// for each project => process pair of user
while ($data2 = mysqli_fetch_assoc($query2)) {
$username = $data['username'];
$projectNo = $data2['projectNo'];
$projectTitle = $data2['title'];
$process = $data2['process'];
$projectNoToTitle[$projectNo] = $projectTitle;
if (!isset($result[$username])) {
$result[$username] = [];
}
if (!isset($result[$username][$projectNo])) {
$result[$username][$projectNo] = [];
}
if ($process) {
$result[$username][$projectNo][] = $process;
}
}
}
// \1.Get data
// 2. Output table
// create table header
// it's columns should contain all projects
if ($result) {
$header =
'<th>username</th>' .
array_reduce(array_values($projectNoToTitle), function ($p, $n) {
return $p . '<th>project ' . htmlspecialchars($n) . '</th>';
});
// output body
$body = '';
foreach ($result as $username => $usernameData) {
$row = '<td>' . htmlspecialchars($username) . '</td>';
foreach ($projectNoToTitle as $projectNo => $projectTitle) {
$r = (isset($usernameData[$projectNo]) && $usernameData[$projectNo])
? implode(', ', $usernameData[$projectNo])
: 'N/A';
$row .= '<td>' . htmlspecialchars($r) . '</td>';
}
$body .= "<tr>$row</tr>";
}
echo "<table><thead>$header</thead><tbody>$body</tbody></table>";
}
// \2. Output table
Feel free to modify if you found some bugs :)
is it possible to get the Column name where a particulare data was found without looping through the result, maybe by PDO? or is there another way to do this in mySQL?
the example show only 3 columns but for my table i may have up to 30 columns need to be check
if i have a table, table1 and want to find the column(s) where 'x' was found
+----+------+------+------+
| id | Col1 | Col2 | Col3 |
+----+------+------+------+
| 0 | x | b | x |
| 1 | x | x | f |
| 2 | d | x | g |
| 3 | h | j | k |
+----+------+------+------+
currentyl i run a Select then loop to each row and check each row column if data is 'x'
$query= "SELECT * FROM table1 WHERE (Col1='x' OR Col2='x' OR Col3='x')"
$result=mysql_query($query);
$foundCols = array();
$rowCnt = 0;
while ($row = mysql_fetch_assoc($result)) {
$tmpArr = array();
if ($row['Col1'] == 'x') {
$tmpArr[] = 'Col1';
}
if ($row['Col2'] == 'x') {
$tmpArr[] = 'Col2';
}
if ($row['Col3'] == 'x') {
$tmpArr[] = 'Col3';
}
$foundCols[$rowCnt] = $tmpArr;
$rowCnt = $rowCnt+1
}
thank you
Try this:
while ($row = mysql_fetch_assoc($result)) {
...
foreach (array('Col1', 'Col2', 'Col3') as $key) {
if ($row[$key] == 'x') {
$tmpArr[] = $key;
}
}
...
}
i have table in database:
Group:
| id | Category | title |
| 1 | 1 | group1 |
| 2 | 2 | group2 |
| 3 | 1 | group3 |
| 4 | 3 | group4 |
| 5 | 2 | group5 |
| 6 | 1 | group6 |
News:
| id | Group | title | body |
| 1 | 3 | title1 | body1 |
| 2 | 2 | title2 | body2 |
| 3 | 1 | title3 | body3 |
| 4 | 4 | title4 | body4 |
| 5 | 1 | title5 | body5 |
| 6 | 5 | title6 | body6 |
| 7 | 3 | title7 | body7 |
| 8 | 2 | title8 | body8 |
| 9 | 1 | title9 | body9 |
| 10 | 6 | title10| body10 |
| 11 | 1 | title11| body11 |
| 12 | 5 | title12| body12 |
how can i show this as:
-GROUP1, GROUP3 and GROUP6
//GROUP1 (category1)
--title3
--title5
--title9
//GROUP3 (category1)
--title1
--title7
//GROUP6 (category1)
--title10
-GROUP2 and GROUP5
//GROUP2 (category2)
--title2
--title8
//GROUP5 (category2)
--title6
--titl12
-GROUP4
//GROUP4 (category3)
--title4
i will make this in foreach. thanks for help!
Your exact requested output makes this complicated.
$sql = 'SELECT n.title, n.Group AS group_id, g.Category AS cat_id
FROM News AS n
JOIN Group AS g ON g.id = group_id
ORDER BY cat_id, group_id, n.id';
$result = mysql_query($query);
$categories = array();
while ($row = mysql_fetch_assoc($result)) {
$catID = $row['cat_id'];
$groupID = $row['group_id'];
$title = $row['title'];
$categories[$catID]['groups'][$groupID]['titles'][] = $title;
}
foreach ($categories as $catID => $groups) {
$catGroups = '-GROUP'.implode(', GROUP',array_keys($groups)).PHP_EOL;
$lastComma = strrpos($catGroups,',');
if ($lastComma !== false) {
$catGroups = substr($catGroups,0,$lastComma-1).
' AND ' .substr($catGroups,$lastComma+1);
}
echo $catGroups;
foreach ($groups as $groupID => $titles) {
echo "//GROUP$groupID (category$catID)".PHP_EOL;
foreach ($groups as $group => $titles) {
echo '--'.$title.PHP_EOL;
}
}
}
If you didn't need such fancy output, this would be much simpler.
$sql = 'SELECT n.title, n.Group AS group_id, g.Category AS cat_id
FROM News AS n
JOIN Group AS g ON g.id = group_id
ORDER BY cat_id, group_id, n.id';
$result = mysql_query($query);
$lastCatID = null;
$lastGroupID = null;
while ($row = mysql_fetch_assoc($result)) {
$catID = $row['cat_id'];
$groupID = $row['group_id'];
$title = $row['title'];
if ($catID !== $lastCatID){
echo "*** CATEGORY $catID\n";
$lastCatID = $catID;
}
if ($groupID !== $lastGroupID){
echo "GROUP $groupID\n";
$lastGroupID = $groupID;
}
echo "-- $title\n";
}
You told, you have your values in the database. So you have to get them first, e.g. with the following database query:
SELECT
g.`title` AS `group_title`
, n.`title` AS `news_title`
FROM
`Group` AS g
INNER JOIN
`News` AS n
ON
g.`id` = n.`Group`
ORDER BY
g.`Category`
, n.`Group`
, n.`title`
Store the data in an array. Now you can use a foreach loop to iterate over the array.
===
Here my update:
First fill the array while reading from the database (example query see above).
<?php
$data = array();
$res = mysql_query('SELECT ...');
while (($row = mysql_fetch_assoc($res)) !== false) {
$data[$row['group_title']][] = $row['news_title'];
}
?>
Then write the array to the screen:
<?php
foreach ($data as $group_title => $groups) {
echo $group_title . "\n";
foreach ($groups as $news) {
echo "\t" . $news . "\n";
}
}
?>
I am trying to get my all categories and sub-categories from MySQL database in a hierarchy:
My result should be like that (just example):
Cat A
Sub-Cat 1
Sub_Sub_Cat 1
Sub_Sub_Cat 2
Sub_Cat 2
Cat B
Cat C
...
MySQL code:
CREATE TABLE IF NOT EXISTS `categories` (
`category_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`parent_id` mediumint(8) unsigned NOT NULL DEFAULT '0' COMMENT 'for sub-categories'
PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
Simply, how can get it in a hirarchy with PHP codes?
When using an adjacency list model, you can generate the structure in one pass.
Taken from One Pass Parent-Child Array Structure (Sep 2007; by Nate Weiner):
$refs = array();
$list = array();
$sql = "SELECT item_id, parent_id, name FROM items ORDER BY name";
/** #var $pdo \PDO */
$result = $pdo->query($sql);
foreach ($result as $row)
{
$ref = & $refs[$row['item_id']];
$ref['parent_id'] = $row['parent_id'];
$ref['name'] = $row['name'];
if ($row['parent_id'] == 0)
{
$list[$row['item_id']] = & $ref;
}
else
{
$refs[$row['parent_id']]['children'][$row['item_id']] = & $ref;
}
}
From the linked article, here's a snippet to create a list for output. It is recursive, if there a children for a node, it calls itself again to build up the subtree.
function toUL(array $array)
{
$html = '<ul>' . PHP_EOL;
foreach ($array as $value)
{
$html .= '<li>' . $value['name'];
if (!empty($value['children']))
{
$html .= toUL($value['children']);
}
$html .= '</li>' . PHP_EOL;
}
$html .= '</ul>' . PHP_EOL;
return $html;
}
Related Question:
How to obtain a nested HTML list from object's array recordset?
I have a new idea I think it will be nice.
The idea is this:
in category_parent column we will insert a reference to all parents of this node.
+----+----------------------+-----------------+
| id | category_name | hierarchy |
+----+----------------------+-----------------+
| 1 | cat1 | 1 |
+----+----------------------+-----------------+
| 2 | cat2 | 2 |
+----+----------------------+-----------------+
| 3 | cat3 | 3 |
+----+----------------------+-----------------+
| 4 | subcat1_1 | 1-4 |
+----+----------------------+-----------------+
| 5 | subcat1_2 | 1-5 |
+----+----------------------+-----------------+
| 6 | subsubcat1_1 | 1-4-6 |
+----+----------------------+-----------------+
| 7 | subsubcat1_2 | 1-4-7 |
+----+----------------------+-----------------+
| 8 | subsubcat1_3 | 1-4-8 |
+----+----------------------+-----------------+
| 9 | subsubcat1_3_1 | 1-4-8-9 |
+----+----------------------+-----------------+
| 10 | subsubcat1_3_2 | 1-4-8-10 |
+----+----------------------+-----------------+
| 11 | subsubcat1_3_1_1 | 1-4-8-9-11 |
+----+----------------------+-----------------+
| 12 | subsubsubcat1_3_1_1 | 1-4-8-9-12 |
+----+----------------------+-----------------+
| 13 | subsubsubcat1_3_1_2 | 1-4-8-9-11-13 |
+----+----------------------+-----------------+
| 14 | subsubsubcat1_2_1_3 | 1-4-8-9-11-14 |
+----+----------------------+-----------------+
if you look at my updated table you will notice that every record has an link to its parents, not only the direct one, But also all of parents.
And for that job I made some modification to insert to be:
Insert into table_name (category_name, hierarchy) values ('new_name', (concat(parent_hierarch, '-', (SELECT Auto_increment FROM information_schema.tables WHERE table_name='table_name'))))
Now lets make your desired queries:
1- all sub categories of cars:
select * from table_name where hierarchy like '1-%'
2- if you need all parent of BLACK you simply type:
select * from table_name where hierarchy = '1-4-8-9' or hierarchy = '1-4-8' or hierarchy = '1-4' or hierarchy = '1'
(you can build that query from php, splitting hierarchy field at '-' char)
3- To see all categories, with level and direct parent:
select *, SUBSTR(hierarchy, 1, (LENGTH(hierarchy) - LENGTH(id) - 1)) as parent, LENGTH(hierarchy) - LENGTH(REPLACE(hierarchy, '-', '')) as level From table_name
+----+----------------------+-----------------+-----------+--------+
| id | category name | hierarchy | parent | level |
+----+----------------------+-----------------+-----------+--------+
| 1 | cat1 | 1 | | 0 |
+----+----------------------+-----------------+-----------+--------+
| 2 | cat2 | 2 | | 0 |
+----+----------------------+-----------------+-----------+--------+
| 3 | cat3 | 3 | | 0 |
+----+----------------------+-----------------+-----------+--------+
| 4 | subcat1_1 | 1-4 | 1 | 1 |
+----+----------------------+-----------------+-----------+--------+
| 5 | subcat1_2 | 1-5 | 1 | 1 |
+----+----------------------+-----------------+-----------+--------+
| 6 | subsubcat1_1 | 1-4-6 | 1-4 | 2 |
+----+----------------------+-----------------+-----------+--------+
| 7 | subsubcat1_2 | 1-4-7 | 1-4 | 2 |
+----+----------------------+-----------------+-----------+--------+
| 8 | subsubcat1_3 | 1-4-8 | 1-4 | 2 |
+----+----------------------+-----------------+-----------+--------+
| 9 | subsubcat1_3_1 | 1-4-8-9 | 1-4-8 | 3 |
+----+----------------------+-----------------+-----------+--------+
| 10 | subsubcat1_3_2 | 1-4-8-10 | 1-4-8 | 3 |
+----+----------------------+-----------------+-----------+--------+
| 11 | subsubcat1_3_1_1 | 1-4-8-9-11 | 1-4-8-9 | 4 |
+----+----------------------+-----------------+-----------+--------+
| 12 | subsubsubcat1_3_1_1 | 1-4-8-9-12 | 1-4-8-9 | 4 |
+----+----------------------+-----------------+-----------+--------+
| 13 | subsubsubcat1_3_1_2 | 1-4-8-9-11-13 |1-4-8-9-11 | 5 |
+----+----------------------+-----------------+-----------+--------+
| 14 | subsubsubcat1_2_1_3 | 1-4-8-9-11-14 |1-4-8-9-11 | 5 |
+----+----------------------+-----------------+-----------+--------+
This is a new idea and need some improvement.
Try the following code
//connect to mysql and select db
$conn = mysqli_connect('localhost', 'user', 'password','database');
if( !empty($conn->connect_errno)) die("Error " . mysqli_error($conn));
//call the recursive function to print category listing
category_tree(0);
//Recursive php function
function category_tree($catid){
global $conn;
$sql = "select * from category where parent_id ='".$catid."'";
$result = $conn->query($sql);
while($row = mysqli_fetch_object($result)):
$i = 0;
if ($i == 0) echo '<ul>';
echo '<li>' . $row->cat_name;
category_tree($row->id);
echo '</li>';
$i++;
if ($i > 0) echo '</ul>';
endwhile;
}
//close the connection
mysqli_close($conn);
?>
More...
#Amnon Your code works perfectly. Just tested it with CodeIgniter and it worked like a charm. Here's the working code if anyone needs it:
<?php
function disTree($all_cats) {
$tree = array();
foreach ($all_cats as $cat)
{
$pid = $cat->parent_id;
$id = $cat->cat_id;
$name = $cat->cat_name;
// Create or add child information to the parent node
if (isset($tree[$pid]))
// a node for the parent exists
// add another child id to this parent
$tree[$pid]["children"][] = $id;
else
// create the first child to this parent
$tree[$pid] = array("children"=>array($id));
// Create or add name information for current node
if (isset($tree[$id]))
// a node for the id exists:
// set the name of current node
$tree[$id]["name"] = $name;
else
// create the current node and give it a name
$tree[$id] = array( "name"=>$name );
}
return $tree;
}
function toUL($tree, $id, $html){
$html .= '<ul>'.PHP_EOL;
if (isset($tree[$id]['name']))
$html .= '<li>' . $tree[$id]['name'];
if (isset($tree[$id]['children']))
{
$arChildren = &$tree[$id]['children'];
$len = count($arChildren);
for ($i=0; $i<$len; $i++) {
$html .= toUL($tree, $arChildren[$i], "");
}
$html .= '</li>'.PHP_EOL;
}
$html .= '</ul>'.PHP_EOL;
return $html;
}
$tree = disTree($all_cats);
// Display the tree
echo toUL($tree, 0, "");
?>
The only thing I changed was adding my own array ($all_cats).
There's another way to achieve the same effect which I find a bit easier to follow (without the reference trick). You build the tree by adding the relevant information to the current node and to its parent (assume the foreach iterates over the returned rows from the SQL query):
$tree = array();
foreach ($query->result() as $row)
{
$pid = $row->parent_id;
$id = $row->id;
$name = $row->name;
// Create or add child information to the parent node
if (isset($tree[$pid]))
// a node for the parent exists
// add another child id to this parent
$tree[$pid]["children"][] = $id;
else
// create the first child to this parent
$tree[$pid] = array("children"=>array($id));
// Create or add name information for current node
if (isset($tree[$id]))
// a node for the id exists:
// set the name of current node
$tree[$id]["name"] = $name;
else
// create the current node and give it a name
$tree[$id] = array( "name"=>$name );
}
return $tree;
and to display the tree:
function toUL($tree, $id, $html){
$html .= '<ul>'.PHP_EOL;
if (isset($tree[$id]['name']))
$html .= '<li>' . $tree[$id]['name'];
if (isset($tree[$id]['children']))
{
$arChildren = &$tree[$id]['children'];
$len = count($arChildren);
for ($i=0; $i<$len; $i++) {
$html .= toUL($tree, $arChildren[$i], "");
}
$html .= '</li>'.PHP_EOL;
}
$html .= '</ul>'.PHP_EOL;
return $html;
}
// Display the tree
echo toUL($tree, 0, "");