PHP generate a tree by specified depth and rules - php

I'm stuck with a tree generating algorithm:
There's no parent-child params, only starting node value
Every node has 2 children (except the last children)
Array example:
$start = 1;
$depth = 3;
$s = array(
'name' => 1, // taken from $start
'children' => array(
array(
'name' => 2,
'children => array(
array( 'name' => 3 ), /* No children for last node $depth */
array( 'name' => 3 ), /* No children for last node $depth */
)
),
array(
'name' => 2,
'children => array(
// same as above
)
),
)
);
At this point I've come up with a very ugly function and would appreciate any help or suggestions to build more nice algorithm.

this should be helpful
function generateTree($depth, $level = 0)
{
$result = array();
if ($depth == $level) {
$result = array('name' => $level);
} else {
$result = array('name' => $level, 'children' => array(generateTree($depth, $level + 1), generateTree($depth, $level + 1)));
}
return $result;
}
print_r(generateTree(3, 1));

Related

different colors for each records in laravel 5

I just want to add different colors for each records within foreach loop.I tried to add but I couldn't make it. Given below is my function.
public function service()
{
$result = Order::getService();
$out = array();
foreach($result as $row) {
$out[] = array(
'id' => $row['orderID'],
'class'=>'event-special',
'title' => $row['customer_name'].' - '.$row['order_number'],
'url' => URL::to('/').'/customer/'.$row['customerID'].'/order/'.$row['orderID'].'/edit',
'start' => strtotime($row['start_date']) . '000',
'end' => strtotime($row['end_date']) .'000'
);
}
return json_encode(array('success' => 1, 'result' => $out));
}
Can anyone please help me with this?
You could create yourself a set of event-special css classes i.e. event-special1, event-special2 ......
And then amend the code to add a number to your existing class
public function service()
{
$result = Order::getService();
$out = array();
$color = 1;
foreach($result as $row) {
$out[] = array(
'id' => $row['orderID'],
'class'=>'event-special' . $color,
'title' => $row['customer_name'].' - '.$row['order_number'],
'url' => URL::to('/').'/customer/'.$row['customerID'].'/order/'.$row['orderID'].'/edit',
'start' => strtotime($row['start_date']) . '000',
'end' => strtotime($row['end_date']) .'000'
);
$color++;
}
return json_encode(array('success' => 1, 'result' => $out));
}

How to show the child nodes of drupal menu

In my admin, I have enabled the Show As Expanded tick, but the submenus do not show.
Here is my code in template.php:
$trail = menu_get_active_trail();
$leaf = $trail[1];
if(!empty($leaf['has_children'])) {
$parameters = array(
'active_trail' => array($leaf['plid']),
'only_active_trail' => FALSE,
'min_depth' => $leaf['depth'] + 1,
'max_depth' => $leaf['depth'] + 2,
'conditions' => array('plid' => $leaf['mlid']),
);
$children = menu_build_tree($leaf['menu_name'], $parameters);
$vars['submenu'] = menu_tree_output($children);
}
EDIT:
The right code is:
$trail = menu_get_active_trail();
$leaf = $trail[1];
if(!empty($leaf['has_children'])) {
$parameters = array(
'active_trail' => array($leaf['plid']),
'min_depth' => $leaf['depth'] + 1,
'max_depth' => $leaf['depth'] + 3,
'conditions' => array('p1' => $leaf['mlid']),
);
$children = menu_build_tree($leaf['menu_name'], $parameters);
$vars['submenu'] = menu_tree_output($children);
}
Thanks.
'conditions' => array('plid' => $leaf['mlid']), may be the problem. You should use p1, p2, ... to filter the parent

Know the element level in multidimensional array

Well, I am here again dealing with arrays in php. I need your hand to guide me in the right direction. Suppose the following array:
-fruits
--green
---limon
---mango
--red
---apple
-cars
--ferrari
---enzo
----blue
----black
---318
--lamborg
---spider
---gallardo
----gallado-96
-----blue
-----red
-----gallado-98
The - (hyphen) symbol only illustrates the deep level.
Well, I need to build another array (or whatever), because it should be printed as an HTML select as below:
-fruits
--green
---limon
---mango
--red
---apple
-cars
--ferrari
---enzo
----blue
----black
---318
--lamborg
---spider
---gallardo
----gallado-96
-----blue
-----red
-----gallado-98
Looks that for each level element, it should add a space, or hyphen to determinate that it belongs to a particular parent.
EDIT
The have provide an answer provideng my final code. The html select element will display each level as string (repeating the "-" at the begging of the text instead multi-level elements.
Here's a simple recursive function to build a select dropdown given an array. Unfortunately I'm not able to test it, but let me know if it works. Usage would be as follows:
function generateDropdown($array, $level = 1)
{
if ($level == 1)
{
$menu = '<select>';
}
foreach ($array as $a)
{
if (is_array($a))
{
$menu .= generateDropdown($a, $level+1);
}
else
{
$menu .= '<option>'.str_pad('',$level,'-').$a.'</option>'."\n";
}
}
if ($level == 1)
{
$menu = '</select>';
}
return $menu;
}
OK, I got it with the help of #jmgardhn2.
The data
This is my array:
$temp = array(
array(
'name' => 'fruits',
'sons' => array(
array(
'name' => 'green',
'sons' => array(
array(
'name' => 'mango'
),
array(
'name' => 'banana',
)
)
)
)
),
array(
'name' => 'cars',
'sons' => array(
array(
'name' => 'italy',
'sons' => array(
array(
'name' => 'ferrari',
'sons' => array(
array(
'name' => 'red'
),
array(
'name' => 'black'
),
)
),
array(
'name' => 'fiat',
)
)
),
array(
'name' => 'germany',
'sons' => array(
array(
'name' => 'bmw',
)
)
),
)
)
);
Recursive function
Now, the following function will provide an array with items like [level] => [name]:
function createSelect($tree, $items, $level)
{
foreach ($tree as $key)
{
if (is_array($key))
{
$items = createSelect($key, $items, $level + 1);
}
else
{
$items[] = array('level' => $level, 'text' => $key);
}
}
return $items;
}
Calling the funcion
Now, call the function as below:
$items = createSelect($temp, array(), 0);
Output
If you iterate the final $items array it will look like:
1fruits
2green
3mango
3banana
1cars
2italy
3ferrari
4red
4black
3fiat
2germany
3bmw

How to Print Binary Tree from the given Database Structure using PHP?

I have a MySQL database in this format :
table name : btree_mst
fields : id, parent_id, left_node_id, right_node_id, user_name
Now what I have to do is print it in the Un-ordered list format like below
Root Node
Node A
Node A Left
Node A Right
Node B
Node B Left
Node B Right
I tried to make a recursive function for that but didn't work as expected.
Any suggestions ?
Here is the Code I made, http://pastebin.com/X15qAKaA
The only bug in this code is, it is printing UL every time. It should print only when the Level is changed.
Thanks in advance.
If you do not have ordered list in your DB, recursion is suitable.
class A
{
private $a = array(
array(
'id' => 1,
'parent_id' => 0,
'title' => 'ROOT'
),
array(
'id' => 2,
'parent_id' => 1,
'title' => 'A'
),
array(
'id' => 3,
'parent_id' => 1,
'title' => 'B'
),
array(
'id' => 4,
'parent_id' => 2,
'title' => 'A left'
)
);//your database values
public function buildTree()
{
$aNodes = array();
$iRootId = 1;//your root id
foreach ($this->a AS $iK => $aV)
{
if($aV['id'] == $iRootId)
{
unset($this->a[$iK]);
$aNodes[$aV['id']] = $aV;
$aNodes[$aV['id']]['childs'] = $this->getChilds($aV['id']);
}
}
print_r($aNodes);//print tree
}
private function getChilds($iParentId)
{
$aChilds = array();
foreach ($this->a AS $iK => $aV)
{
if($aV['parent_id'] == $iParentId)
{
unset($this->a[$iK]);
$aChilds[$aV['id']] = $aV;
$aChilds[$aV['id']]['childs'] = $this->getChilds($aV['id']);
}
}
return $aChilds;
}
}
$o = new A();
$o->buildTree();

How to sort flat array into multidimensional tree

I have a table like
id catagory suboff
1 software 0
2 programming 1
3 Testing 1
4 Designing 1
5 Hospital 0
6 Doctor 5
7 Nurses 5
9 Teaching 0
10 php programming 2
11 .net programming 2
How to write a code to get all these information in a multidimensional array based on the suboff as follows,
-software
--programming
---php programming
--- .net programming
--testing
--designing
-hospital
--doctor
--nurses
-teaching
Assuming MySQL as your DB engine:
// We'll need two arrays for this
$temp = $result = array();
// Get the data from the DB
$table = mysql_query("SELECT * FROM table");
// Put it into one dimensional array with the row id as the index
while ($row = mysql_fetch_assoc($table)) {
$temp[$row['id']] = $row;
}
// Loop the 1D array and create the multi-dimensional array
for ($i = 1; isset($temp[$i]); $i++) {
if ($temp[$i]['suboff'] > 0) {
// This row has a parent
if (isset($temp[$temp[$i]['suboff']])) {
// The parent row exists, add this row to the 'children' key of the parent
$temp[$temp[$i]['suboff']]['children'][] =& $temp[$i];
} else {
// The parent row doesn't exist - handle that case here
// For the purposes of this example, we'll treat it as a root node
$result[] =& $temp[$i];
}
} else {
// This row is a root node
$result[] =& $temp[$i];
}
}
// unset the 1D array
unset($temp);
// Here is the result
print_r($result);
Use references for a job like this.
Demo: http://ideone.com/vk4po
$array = array(
array('1','software','0'),
array('2','programming','1'),
array('3','Testing','1'),
array('4','Designing','1'),
array('5','Hospital','0'),
array('6','Doctor','5'),
array('7','Nurses','5'),
array('9','Teaching','0'),
array('10','php programming','2'),
array('11','.net programming','2')
);
function menu_sort($results, $master = 0)
{
$open = array();
$return = NULL;
foreach($results as $result)
{
if($result[2] == $master){
if(!$open){
$return .= '<ul>';
$open = true;
}
$return .= '<li>'.$result[1];
$return .= menu_sort($results, $result[0]);
$return .= '</li>';
}
}
if($open)
$return .= '</ul>';
return $return;
}
echo menu_sort($array);
Result...
software
programming
php programming
.net programming
Testing
Designing
Hospital
Doctor
Nurses
Teaching
The way I would do that:
First you need to parse this table. I assume you can do it yourself; if not, Google "regular expressions", they are your friends.
The data structure you are working with is a classical tree. You will need two arrays to work with it. First is an array of nodes, $nodes, where the keys are the node IDs and values are node names, and $links, where each key is a parent node and each value is an array of children ($links[$id][] = $suboff for each element would suffice).
Now you have to recursively descent the tree you have. You introduce a function with a signature like this:
function print_node( $nodeID, $level = 1 )
This function should print the node itself (info stored in $nodes) with $level padding dashes and call itself to render all children nodes. They will in turn render all their subnodes, etc. You just have to call this function for top-level nodes.
This class converst a flat category array into a structured tree array:
<?php
/**
* Creates a structured tree out of a flat category list
*/
class CategoryTree {
/**
*
* #var array
*/
protected $categories = array();
/**
*
* #var array
*/
protected $tree = array();
/**
* Default constructor
* #param array $categories
*/
function __construct(array $categories) {
$this->categories = $categories;
}
/**
* Process a subtree
* #param array $categories
* #param integer $parentId
* #return array
*/
protected function getSubtree(array $categories, $parentId = 0) {
$tree = array();
foreach($categories as $category) {
if($category['suboff'] == $parentId) {
$tree[$category['id']] = $category;
$tree[$category['id']]['children'] = $this->getSubtree($categories, $category['id']);
}
}
return $tree;
}
/**
* Get the category tree as structured array
* #return array
*/
public function getTree() {
if(empty($this->tree)) {
$this->tree = $this->getSubtree($this->categories, 0);
}
return $this->tree;
}
/**
* Get the category tree as string representation
* #return string
*/
public function __toString() {
return "<pre>" . print_r($this->getTree(), true) . "</pre>";
}
}
// Now, use the class with the givven data:
$categories = array(
array(
'id' => 1,
'category' => 'software',
'suboff' => 0
),
array(
'id' => 2,
'category' => 'programming',
'suboff' => 1
),
array(
'id' => 3,
'category' => 'Testing',
'suboff' => 1
),
array(
'id' => 4,
'category' => 'Designing',
'suboff' => 1
),
array(
'id' => 5,
'category' => 'Hospital',
'suboff' => 0
),
array(
'id' => 6,
'category' => 'Doctor',
'suboff' => 5
),
array(
'id' => 7,
'category' => 'Nurses',
'suboff' => 5
),
array(
'id' => 9,
'category' => 'Teaching',
'suboff' => 0
),
array(
'id' => 10,
'category' => 'php programming',
'suboff' => 2
),
array(
'id' => 11,
'category' => '.net programming',
'suboff' => 2
)
);
$myTree = new CategoryTree($categories);
echo $myTree;
?>
This is what I just wrote for my app, and it works like a charm :)
$array = [
'i' => ['key' => 'i', 'name' => 'php programming', 'parent' => 'b'],
'g' => ['key' => 'g', 'name' => 'Nurses', 'parent' => 'e'],
'j' => ['key' => 'j', 'name' => '.net programming', 'parent' => 'b'],
'b' => ['key' => 'b', 'name' => 'programming', 'parent' => 'a'],
'a' => ['key' => 'a', 'name' => 'software', 'parent' => 'asd'],
'c' => ['key' => 'c', 'name' => 'Testing', 'parent' => 'a'],
'd' => ['key' => 'd', 'name' => 'Designing', 'parent' => 'a'],
'e' => ['key' => 'e', 'name' => 'Hospital', 'parent' => 'asd'],
'f' => ['key' => 'f', 'name' => 'Doctor', 'parent' => 'e'],
'h' => ['key' => 'h', 'name' => 'Teaching'],
];
function getAsTree(array &$array)
{
foreach ($array as $key => $item) {
if (isset($item['parent']) && isset($array[$item['parent']])) {
$array[$item['parent']]['children'][] = $item;
unset($array[$key]);
return getAsTree($array);
}
}
return $array;
}
And here is the result:
--- a: software
------ b: programming
--------- i: php programming
--------- j: .net programming
------ c: Testing
------ d: Designing
--- e: Hospital
------ g: Nurses
------ f: Doctor
--- h: Teaching
IMHO the logic is:
Get all the roots element (software, hospital and so on)
Foreach root take the subelement(s) (for the software you'll take programming, testing and designing)
Add the subelement(s) as subarray
Loop recursively on the subarray(s) you just add
You'll want to read the whole table into memory and turn it into a tree where each node can be identified with its corresponding id number. Then do a pre-order traversal of the tree to print it out.
In PHP wenn i get the data from a Database:
"SELECT* FROM Table WHERE suboff LIKE 0"
foreach(item..)
"SELECT* FROM Table WHERE suboff LIKE item.ID"
foreach(item2..)
$result[item][item2]
Here is a different approach that should be very easy to understand. It requires you to have the table ordered by suboff, i.e.
SELECT * FROM table ORDER BY suboff
Assuming the result is stored in $table, you can use this very concise php code:
// this will hold the result
$tree = array();
// used to find an entry using its id
$lookup = array();
foreach($table as $row){
if($row['suboff'] === 0){
// this has no parent, add it at base level
$tree[$row['category']] = array();
// store a reference
$lookup[$row['id']] =& $tree[$row['category']];
}else{
// find the right parent, add the category
$lookup[$row['suboff']][$row['category']] = array();
// store a reference
$lookup[$row['id']] =& $lookup[$row['suboff']][$row['category']];
}
}
This solution works fine for me.
$array = array(
array('1','software','0'),
array('2','programming','1'),
array('3','Testing','1'),
array('4','Designing','1'),
array('5','Hospital','0'),
array('6','Doctor','5'),
array('7','Nurses','5'),
array('9','Teaching','0'),
array('10','php programming','2'),
array('11','.net programming','2')
);
$newArray = getTree($array);
function getTree( $rows, $suboff = 0) {
$return = array();
foreach($rows as $row) {
if($row[2] == $suboff){
$newrow = $row;
$subs = $this->getTree($rows, $row[0]);
if ( !empty($subs) ) {
$newrow['subs'] = $subs;
}
$return[] = $newrow;
}
}
return $return;
}

Categories