4

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
Dejan Marjanović
  • 19,244
  • 7
  • 52
  • 66
Sunil Kumar P
  • 59
  • 1
  • 3
  • What you mean? Where the data comes from? Database or a file or hardcodet? – San Oct 24 '11 at 11:33
  • possible duplicate of [PHP Reorder array to reflect parent / id hierarchy](http://stackoverflow.com/questions/4216875/php-reorder-array-to-reflect-parent-id-hierarchy) or [Convert flat array to the multi-dimentional](http://stackoverflow.com/questions/3261228/convert-flat-array-to-the-multi-dimentional) and [many more](http://stackoverflow.com/search?q=php+nest+array+by+parent+id&submit=search) – mario Oct 24 '11 at 11:36

10 Answers10

3

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.

DaveRandom
  • 87,921
  • 11
  • 154
  • 174
1

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
dzona
  • 3,323
  • 3
  • 31
  • 47
1

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
Dejan Marjanović
  • 19,244
  • 7
  • 52
  • 66
1

The way I would do that:

  1. First you need to parse this table. I assume you can do it yourself; if not, Google "regular expressions", they are your friends.

  2. 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).

  3. 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.

Victor Vasiliev
  • 462
  • 2
  • 12
1

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;

?>
Stefan
  • 21
  • 1
0

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;

}
Hevelson Rosario
  • 420
  • 6
  • 11
0

IMHO the logic is:

  1. Get all the roots element (software, hospital and so on)
  2. Foreach root take the subelement(s) (for the software you'll take programming, testing and designing)
  3. Add the subelement(s) as subarray
  4. Loop recursively on the subarray(s) you just add
Aurelio De Rosa
  • 21,856
  • 8
  • 48
  • 71
0

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.

0

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]
San
  • 868
  • 1
  • 9
  • 18
  • This is very inefficient, because you have to make a lot of queries. It's better to query the data once and let php do the lifting in memory (see my answer). – middus Oct 24 '11 at 13:11
  • okay.. I used this above for menus and theres not much data. But your right my solution is not very good expandable. – San Oct 24 '11 at 13:32
0

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']];
  }
}
middus
  • 9,103
  • 1
  • 31
  • 33