Category Hierarchy (PHP/MySQL) - php

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, "");

Related

Generate JSON booleans from Db

I need to generate a JSON String using this format:
{"content":{"brands":1},"brands":[{"id":"1","name":"brand 1","description":"description","icon":"icon","url":"example.com","categories":{"1":"true","2":"true","3":"false","4":"false","5":"false","6":"false"}},{"id":"2","name":"brand2","description":"description","icon":"icon","url":"example.com","categories":{"1":"true","2":"true","3":"false","4":"false","5":"false","6":"false"}}]}
From this tables:
brands:
| id | name | description | icon | url |
|----|--------|-------------|------|-----|
| 1 | name 1 | description | icon | url |
| 2 | name 2 | description | icon | url |
| 3 | name 3 | description | icon | url |
| 4 | name 4 | description | icon | url |
| 5 | name 5 | description | icon | url |
| 6 | name 6 | description | icon | url |
categories:
| id | name | description | icon | url |
|----|--------|-------------|------|-----|
| 1 | name 1 | description | icon | url |
| 2 | name 2 | description | icon | url |
| 3 | name 3 | description | icon | url |
| 4 | name 4 | description | icon | url |
| 5 | name 5 | description | icon | url |
| 6 | name 6 | description | icon | url |
objects:
| id | id_brand | id_category |name | description | icon | url |
|----|----------|-------------|-------|-------------|------|-----|
| 1 | 1 | 1 |name 1 | description | icon | url |
| 2 | 1 | 2 |name 2 | description | icon | url |
| 3 | 2 | 1 |name 3 | description | icon | url |
| 4 | 2 | 2 |name 4 | description | icon | url |
this is my relevant code so far
public function actionBrand($id = null) {
if (empty($id)) {
// Obtiene datos de la base
$sql = "SELECT DISTINCT objects.id_brand AS id, brands.name AS name, brands.description AS description, brands.icon AS icon, brands.url AS url, objects.id_category, categories.name AS category " .
"FROM objects " .
"LEFT JOIN brands ON objects.id_brand = brands.id " .
"LEFT JOIN categories ON objects.id_category = categories.id " .
"ORDER BY objects.id_brand, objects.id_category ";
} else {
// Obtiene datos de la base
$sql = "SELECT DISTINCT objects.id_brand AS id, brands.name AS name, brands.description AS description, brands.icon AS icon, brands.url AS url, objects.id_category, categories.name AS category " .
"FROM objects " .
"LEFT JOIN brands ON objects.id_brand = brands.id " .
"LEFT JOIN categories ON objects.id_category = categories.id " .
"WHERE brands.id = " . (int) $id . " " .
"ORDER BY objects.id_brand, objects.id_category ";
}
$data = Yii::$app->db->createCommand($sql)
->queryAll();
// Obtiene categorias
$categories = Yii::$app->db->createCommand('SELECT id FROM categories ORDER BY id')
->queryAll();
if (!empty($data)) {
// Construye primer registro
$brands[0]['id'] = $data[0]['id'];
$brands[0]['name'] = $data[0]['name'];
$brands[0]['description'] = $data[0]['description'];
$brands[0]['icon'] = $data[0]['icon'];
$brands[0]['url'] = $data[0]['url'];
$total = count($data);
for ($i = 1, $j = 0; $i < $total; $i++) {
if ($brands[$j]['id'] == $data[$i]['id']) {
continue;
} else {
$j++;
$brands[$j]['id'] = $data[$i]['id'];
$brands[$j]['name'] = $data[$i]['name'];
$brands[$j]['description'] = $data[$i]['description'];
$brands[$j]['icon'] = $data[$i]['icon'];
$brands[$j]['url'] = $data[$i]['url'];
}
}
} else {
$brands = array();
}
// Construye y envia JSON
$json['content']['brands'] = count($brands);
$json['brands'] = $brands;
echo json_encode($json);
}
It generates the first part of the JSON that i need, but im stuck at the categories part i need to select the data from the base and convert it to id : (true)(false) on each brand
{"content":{"brands":1},"brands":[{"id":"1","name":"brand 1","description":"description","icon":"icon","url":"example.com"},{"id":"2","name":"brand2","description":"description","icon":"icon","url":"example.com"}]}
Can you help me?
Regards
After you are done building the brands, loop on the categories, searching brands for the existing id match. If it matches, then adjust a true false value for the categories. Then when the categories are completed, append them to every brand in a final loop.
$cleancats = [];
foreach ($categories as $cat) {
$result = false;
foreach($brands as $brand) {
if ($cat['id'] == $brand['id']) {
$result = true; break;
}
}
$cleancats[ $cat['id'] ] = $result;
}
array_walk ($brands,function(&$brand) use ($cleancats) {
$brand['categories'] = $cleancats;
});
(note put this after your for ($i = 1, $j = 0; $i < $total; $i++) loop ends)
That should get the categories to every brand in brands, as you would like.
If you need the categories to be a LITERAL "true" and "false" then adjust this one line above:
$cleancats[ $cat['id'] ] = ($result?'true':'false');

Find insert position and number of childs in a binary tree using php mysql

below is my table data
+-------------+-----------+----------------+
| customer_id | parent_id | node_direction |
+-------------+-----------+----------------+
| 1 | 0 | T |
| 2 | 1 | L |
| 3 | 1 | R |
| 4 | 2 | L |
| 5 | 2 | R |
| 6 | 4 | L |
+-------------+-----------+----------------+
Which represents the following tree
1
|
---------
| |
2 3
|
-------
| |
4 5
|
-----
|
6
I need to find the position for insertion by parent id
For Example:
1) if parent id is 1 then insert position will be root-3 position-L
2) if parent_id is 2 then insert position will be root-4 position-R
3) if parent_id is 3 then insert position will be root-3 position-L
The thing is it need to follow the binary structure
I also need to have count of sub nodes by parent node for example:
1 - 5
2 - 3
3 - 0
4 - 1
5 - 0
I need to accomplish this in php and mysql.
Can anyone suggest to me the easiest way to achieve this?
function getNodeInsertPostionByParentId($parentId){
$position = array('status'=>false);
$parents = array();
foreach($parentId as $parent){
$qry = "select customer_id,node_direction from mlm_nodes where parent_id =".$parent." order by node_direction";
$rst = mysql_query($qry);
$count = mysql_num_rows($rst);
if($count==2){
while($row = mysql_fetch_assoc($rst)){
$parents[$parent][] = $row['customer_id'];
}
}elseif($count==1){
$position['status'] = true;
$position['parentId'] = $parent;
$position['node'] = 'R';
//echo '<pre>1';print_r($position);echo '</pre>';
return $position;
}else{
$position['status'] = true;
$position['parentId'] = $parent;
$position['node'] = 'L';
//echo '<pre>2';print_r($position);echo '</pre>';
return $position;
}
}
return $this->searchByParents($parents);
}
function searchByParents($parents){
foreach($parents as $parent){
return $this->getNodeInsertPostionByParentId($parent);
}
}
echo '<pre>';print_r($this->getNodeInsertPostionByParentId(array('4')));die;
This works as expected for finding node position by parent id

SQL Query and PHP manipulation with Nested Set Model

I was reading this article, http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/.
I wanted to give a simple example and then ask you how do I get the desired result? So here is the example:
+---------+-----------------------------+
| product_id | product_name |
+---------+-----------------------------+
| 1 | Example Product |
+---------+-----------------------------+
+---------+-----------------------------+
| product_id | category_id |
+---------+-----------------------------+
| 1 | 2 |
| 1 | 4 |
+---------+-----------------------------+
+-------------+--------------------+------+------+
| category_id | name | lft | rgt |
+-------------+--------------------+------+------+
| 1 | Electronics | 1 | 8 |
| 2 | Televisions | 2 | 3 |
| 3 | Portable Electronics | 4 | 7 |
| 4 | CD Players | 5 | 6 |
+-------------+--------------------+------+------+
I want to be able to display the following result in HTML after querying and then manipulating the data in PHP:
"Example Product" Categories:
Electronics
Televisions
Portable Electronics
CD Players
Can you help walk me through the query and manipulation in PHP to achieve this result?
Some specifics to think about:
Notice how both categories are under Electronics, but "Electronics" appears only once here, displaying each of the subcategories it belongs to below
The result should eventually be a PHP multi-dimensional array with the category containing an array of sub-categories and each sub-category containing an array of sub-subcategories if they exist.
I imagine printing the depth will be very important for constructing the right tree in HTML.
I thought this was a nice challenge .. here's my solution:
Basically: read a node, then all following nodes with a rgt smaller than your rgt are your children, do this recursively.
I've used a peek/consume to read from mysql like you normally would.
The script will break or loop if the query gives no results, or if the data-set is broken.
class NestedNodeReader {
private $mysql_result;
private $peeked = false;
private $last_peek;
public function __construct($mysql_result) {
$this->mysql_result = $mysql_result;
}
public function getTree() {
$root = $this->consume();
$root["children"] = $this->getSubTree($root["rgt"]);
return $root;
}
private function getSubTree($stop_at) {
$nodes = array();
$node = $this->peek();
while ($node["rgt"] < $stop_at) {
$node = $this->consume();
$node["children"] = $this->getSubTree($node["rgt"]);
$nodes[] = $node;
$node = $this->peek();
if (false === $node) {
break;
}
}
return $nodes;
}
private function peek() {
if (false === $this->peeked) {
$this->peeked = true;
$this->last_peek = mysql_fetch_assoc($this->mysql_result);
}
return $this->last_peek;
}
private function consume() {
if (false === $this->peeked) {
return mysql_fetch_assoc($this->mysql_result);
} else {
$this->peeked = false;
return $this->last_peek;
}
}
}
$query = "SELECT node.name, node.lft, node.rgt
FROM nested_category AS node,
nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND parent.name = 'ELECTRONICS'
ORDER BY node.lft;"
$mysql_result = mysql_query($query);
$nnr = new NestedNodeReader($mysql_result);
print_r($nnr->getTree());

foreach for groups and subgroups in php

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";
}
}
?>

mysql + php retrieve leaf children with path

I have a table that like this.
+-----------+-----------+-----------+-----------+-----------+-----------+
|id | parent_id | name | order | status | date_add |
+-----------+-----------+-----------+-----------+-----------+-----------+
|1 | 0 | shoes | 1 | 1 | 2011-04-02|
+-----------+-----------+-----------+-----------+-----------+-----------+
|2 | 1 | male | 2 | 1 | 2011-04-02|
+-----------+-----------+-----------+-----------+-----------+-----------+
|3 | 1 | female | 3 | 1 | 2011-04-02|
+-----------+-----------+-----------+-----------+-----------+-----------+
|4 | 3 | red shoes | 4 | 1 | 2011-04-02|
+-----------+-----------+-----------+-----------+-----------+-----------+
I want to select only the leaf children, with their path.
I want to come to the result as follows:
+------+-------------------------------------+
| 2 | shoes/male |
+------+-------------------------------------+
| 4 | shoes/female/red shoes |
+------+-------------------------------------+
if this does not only sql can also be php + sql
Please help me.
Very simple solution to print out id and path to all last child nodes using PHP as I am not aware of a way of doing this within MySQL. Hope this helps!
function getChildren($parent= "", $x = 0) {
$sql = "SELECT id, name FROM recurr WHERE parentId = $x";
$rs = mysql_query($sql);
//echo "Name: $parent has ". mysql_num_rows($rs)." children<br/>";
while ($obj = mysql_fetch_object($rs)) {
if (hasChildren($obj->id)) {
getChildren($parent."/".$obj->name, $obj->id);
} else {
echo $obj->id .", ".$parent."/".$obj->name."<br/>";
}
}
}
function hasChildren($x) {
$sql = "SELECT * FROM recurr WHERE parentId = $x";
$rs = mysql_query($sql);
if (mysql_num_rows($rs) > 0) {
return true;
} else {
return false;
}
}
To run just call:
getChildren();
I highly recommend implementing nested set model for hierarchical MySQL data. Here is the link for more info: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/. In the link, you will also find the answer to your question (under "The Adjacency List Model", "Finding all the Leaf Nodes" section)

Categories